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.