This JavaScript program demonstrates how to rotate a cube with faces on a canvas element using arrow key controls.
<!DOCTYPE html>
<html>
<head>
<title>XoaX.net's Javascript Perceptron Learning</title>
<script type="text/javascript" src="RotateCubeWithFaces.js"></script>
<style>
.cFocus { border: 1px red solid; }
.cBlur { border: none; }
</style>
</head>
<body onload="Initialize()">
<canvas id="idCanvas" width="640" height ="480" style="background-color: #F0F0F0;"></canvas>
</body>
</html>class CCanvasPlane {
constructor() {
var qCanvas = document.getElementById("idCanvas");
this.mqContext = qCanvas.getContext("2d");
this.mqAlpha = Math.PI/6;
this.mqBeta = Math.PI/6;
}
Clear() {
this.mqContext.clearRect(0, 0, 640, 480);
}
Left() {
this.mqAlpha += Math.PI/12;
}
Right() {
this.mqAlpha -= Math.PI/12;
}
Up() {
if (this.mqBeta + Math.PI/12 < Math.PI/2 - .01) {
this.mqBeta += Math.PI/12;
}
}
Down() {
if (this.mqBeta - Math.PI/12 > -Math.PI/2 + .01) {
this.mqBeta -= Math.PI/12;
}
}
CreateCoordinateVectors() {
var daaA = [];
daaA[0] = [Math.cos(this.mqAlpha), Math.sin(this.mqAlpha), 0];
daaA[1] = [-daaA[0][1]*Math.sin(this.mqBeta), daaA[0][0]*Math.sin(this.mqBeta), Math.cos(this.mqBeta)];
daaA[2] = [daaA[0][1]*daaA[1][2] - daaA[0][2]*daaA[1][1],
daaA[0][2]*daaA[1][0] - daaA[0][0]*daaA[1][2],
daaA[0][0]*daaA[1][1] - daaA[0][1]*daaA[1][0]];
return daaA;
}
// The projection onto y (up) is in the opposite direction of the canvas pixels
// The z-axis points into the viewing plane
ProjectPointToCoordinates(daP) {
var daaCoord = this.CreateCoordinateVectors();
var daProj = [];
for (var i = 0; i < 3; ++i) {
daProj[i] = daaCoord[i][0]*daP[0] + daaCoord[i][1]*daP[1] + daaCoord[i][2]*daP[2];
}
return daProj;
}
ProjectionToPixel(daP) {
return [320 + daP[0], 240 - + daP[1]];
}
DrawLine(dX1, dY1, dX2, dY2, sColor) {
this.mqContext.globalAlpha = 1.0;
this.mqContext.strokeStyle = sColor;
this.mqContext.beginPath();
this.mqContext.moveTo(dX1, dY1);
this.mqContext.lineTo(dX2, dY2);
this.mqContext.stroke();
}
DrawCubeFaces() {
// The z-vector points toward us. So, if its coordinate is postive, we draw the low side first.
var daBasis = this.CreateCoordinateVectors();
var saColors = ["#FF8080", "#80FF80", "#8080FF", "#80FFFF", "#FF80FF", "#FFFF80"];
const kdLow = -100;
const kdHigh = 100;
var daRange = [kdLow, kdHigh];
for (var j = 0; j < 2; ++j) {
// Select the axis: 0 = x, 1 = y, 2 = z
for (var i = 0; i < 3; ++i) {
// Select the far side and then the close side
var saSideColors = [saColors[i+3], saColors[i]];
var daSides = [kdLow, kdHigh];
if (daBasis[2][i] < 0) {
daSides[0] = kdHigh;
daSides[1] = kdLow;
saSideColors[0] = saColors[i];
saSideColors[1] = saColors[i+3];
}
// Choose the first vextex on the side with the lowest coordinates
this.mqContext.beginPath();
var daP1 = [0,0,0];
daP1[i] = daSides[j];
daP1[(i+1)%3] = daRange[0];
daP1[(i+2)%3] = daRange[0];
var daProj1 = this.ProjectPointToCoordinates(daP1);
var daPixel1 = this.ProjectionToPixel(daProj1);
this.mqContext.moveTo(daPixel1[0], daPixel1[1]);
// Draw the other three vertices of the side
for (var k = 0; k < 3; ++k) {
var iC1 = ((k < 2) ? 1 : 0);
var iC2 = ((k > 0) ? 1 : 0);
daP1[(i+1)%3] = daRange[iC1];
daP1[(i+2)%3] = daRange[iC2];
daProj1 = this.ProjectPointToCoordinates(daP1);
daPixel1 = this.ProjectionToPixel(daProj1);
this.mqContext.lineTo(daPixel1[0], daPixel1[1]);
}
this.mqContext.globalAlpha = .5;
this.mqContext.closePath();
this.mqContext.strokeStyle = "black";
this.mqContext.lineWidth = 1;
this.mqContext.stroke();
this.mqContext.globalAlpha = .9;
this.mqContext.fillStyle = saSideColors[j];
this.mqContext.fill();
this.mqContext.globalAlpha = 1.0;
}
}
}
DrawAxes() {
this.mqContext.lineWidth = 1;
var saColors = ["red", "green", "blue"];
var daProjOrigin = this.ProjectPointToCoordinates([0,0,0]);
var daOriginPixel = this.ProjectionToPixel(daProjOrigin);
const kdLength = 300;
for (var i = 0; i < 3; ++i) {
var daEndpoint = [0,0,0];
daEndpoint[i] = kdLength;
var daProjEnd = this.ProjectPointToCoordinates(daEndpoint);
var daPixelEnd = this.ProjectionToPixel(daProjEnd);
this.DrawLine(daOriginPixel[0], daOriginPixel[1], daPixelEnd[0], daPixelEnd[1], saColors[i]);
}
}
}
var qCP = null;
function Initialize() {
qCP = new CCanvasPlane();
qCP.DrawCubeFaces();
qCP.DrawAxes();
window.onkeydown=KeyDownFunction;
window.addEventListener("focus", FocusFunction);
window.addEventListener("blur", BlurFunction);
window.focus();
FocusFunction();
}
function FocusFunction() {
document.getElementById("idCanvas").className ='cFocus';
}
function BlurFunction() {
document.getElementById("idCanvas").className ='cBlur';
}
function KeyDownFunction(e) {
var iKeyUp = 38;
var iKeyLeft = 37;
var iKeyRight = 39;
var iKeyDown = 40;
var iKeyCode = 0;
if (e) {
iKeyCode = e.which;
} else {
iKeyCode = window.event.keyCode;
}
qCP.Clear();
switch (iKeyCode) {
case iKeyUp: {
qCP.Up();
// Prevent the window scrolling
e.preventDefault();
break;
}
case iKeyLeft: {
qCP.Left();
// Prevent the window scrolling
e.preventDefault();
break;
}
case iKeyRight: {
qCP.Right();
// Prevent the window scrolling
e.preventDefault();
break;
}
case iKeyDown: {
qCP.Down();
// Prevent the window scrolling
e.preventDefault();
break;
}
default: {
break;
}
}
qCP.DrawCubeFaces();
qCP.DrawAxes();
}
© 20072025 XoaX.net LLC. All rights reserved.