Last active
April 10, 2024 20:45
-
-
Save thomasdarimont/8c694b4522c6cb10d85c to your computer and use it in GitHub Desktop.
Spinning Cube with HTML5, Canvas, JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>Spinning Cube</title> | |
<script type="text/javascript"> | |
function Point3D(x,y,z) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.rotateX = function(currentAngle) { | |
var rad = currentAngle * Math.PI / 180; | |
var cosa = Math.cos(rad); | |
var sina = Math.sin(rad); | |
var y = this.y * cosa - this.z * sina; | |
var z = this.y * sina + this.z * cosa; | |
return new Point3D(this.x, y, z); | |
}; | |
this.rotateY = function(currentAngle) { | |
var rad = currentAngle * Math.PI / 180; | |
var cosa = Math.cos(rad); | |
var sina = Math.sin(rad); | |
var z = this.z * cosa - this.x * sina; | |
var x = this.z * sina + this.x * cosa; | |
return new Point3D(x,this.y, z); | |
}; | |
this.rotateZ = function(currentAngle) { | |
var rad = currentAngle * Math.PI / 180; | |
var cosa = Math.cos(rad); | |
var sina = Math.sin(rad); | |
var x = this.x * cosa - this.y * sina; | |
var y = this.x * sina + this.y * cosa; | |
return new Point3D(x, y, this.z); | |
}; | |
this.project = function(viewWidth, viewHeight, fieldOfView, viewDistance) { | |
var factor = fieldOfView / (viewDistance + this.z); | |
var x = this.x * factor + viewWidth / 2; | |
var y = this.y * factor + viewHeight / 2; | |
return new Point3D(x, y, this.z); | |
}; | |
} | |
var vertices = [ | |
new Point3D(-1,1,-1), | |
new Point3D(1,1,-1), | |
new Point3D(1,-1,-1), | |
new Point3D(-1,-1,-1), | |
new Point3D(-1,1,1), | |
new Point3D(1,1,1), | |
new Point3D(1,-1,1), | |
new Point3D(-1,-1,1) | |
]; | |
var cubeFaces = [[0,1,2,3],[1,5,6,2],[5,4,7,6],[4,0,3,7],[0,4,5,1],[3,2,6,7]] | |
var currentAngle = 0; | |
var screen = { | |
w : 64, | |
h: 64 | |
}; | |
function startRendering() { | |
var canvas = document.getElementById("renderScreen"); | |
if (canvas && canvas.getContext) { | |
canvas.width = screen.w; | |
canvas.height = screen.h; | |
ctx = canvas.getContext("2d"); | |
ctx.strokeStyle = "rgb(255,15,155)" | |
requestAnimationFrame(renderLoop); | |
} | |
} | |
function renderLoop() { | |
var points = new Array(); | |
ctx.fillRect(0,0, screen.h, screen.w); | |
vertices.map(function(vertex){ | |
points.push(vertex.rotateX(currentAngle).rotateY(currentAngle).rotateZ(currentAngle).project(screen.h, screen.w,128,7)); | |
}); | |
cubeFaces.map(function(cubeFace){ | |
ctx.beginPath(); | |
ctx.moveTo(points[cubeFace[0]].x,points[cubeFace[0]].y); | |
ctx.lineTo(points[cubeFace[1]].x,points[cubeFace[1]].y); | |
ctx.lineTo(points[cubeFace[2]].x,points[cubeFace[2]].y); | |
ctx.lineTo(points[cubeFace[3]].x,points[cubeFace[3]].y); | |
ctx.closePath(); | |
ctx.stroke(); | |
}); | |
currentAngle += 2; | |
requestAnimationFrame(renderLoop); | |
} | |
window.onload = startRendering; | |
</script> | |
<style> | |
body { | |
background-color: rgb(0, 0, 0); | |
} | |
#renderScreen { | |
transform: translate(200px, 120px) scale(5, 5); | |
image-rendering: optimizeQuality; | |
/* image-rendering: optimizeSpeed; */ | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="renderScreen"/> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks! I just updated the example to use
requestAnimationFrame
instead ofsetInterval
.Your examples look really nice, thanks for sharing as well :)