this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at canon 104 lines 2.6 kB view raw
1 2<!DOCTYPE html> 3<html lang="en"> 4<head> 5<meta charset="utf-8"> 6<title>Subjective Necker Cube</title> 7<style> 8 html,body{ 9 margin:0; 10 height:100%; 11 display:flex; 12 align-items:center; 13 justify-content:center; 14 background:#fff; /* white background */ 15 } 16</style> 17</head> 18<body> 19<canvas id="cube" width="512" height="512"></canvas> 20 21<script> 22(() => { 23 const canvas = document.getElementById('cube'); 24 const ctx = canvas.getContext('2d'); 25 const W = canvas.width; 26 const H = canvas.height; 27 const CX = W / 2; 28 const CY = H / 2; 29 30 const SCALE = 80; 31 const DISK_RADIUS = 24; 32 const EDGE_THICK = 12; 33 34 const VERTS = [ // corner coordinates of unit cube 35 [-1,-1,-1],[ 1,-1,-1],[ 1, 1,-1],[-1, 1,-1], 36 [-1,-1, 1],[ 1,-1, 1],[ 1, 1, 1],[-1, 1, 1], 37 ]; 38 const EDGES = [ // pairs of vertex indices 39 [0,1],[1,2],[2,3],[3,0], 40 [4,5],[5,6],[6,7],[7,4], 41 [0,4],[1,5],[2,6],[3,7], 42 ]; 43 44 function rotate([x0,y0,z0], yaw, pitch, roll){ 45 // yaw (y axis) 46 let x = x0*Math.cos(yaw) + z0*Math.sin(yaw); 47 let z = -x0*Math.sin(yaw) + z0*Math.cos(yaw); 48 let y = y0; 49 50 // pitch (x axis) 51 [y,z] = [y*Math.cos(pitch) - z*Math.sin(pitch), 52 y*Math.sin(pitch) + z*Math.cos(pitch)]; 53 54 // roll (z axis) 55 [x,y] = [x*Math.cos(roll) - y*Math.sin(roll), 56 x*Math.sin(roll) + y*Math.cos(roll)]; 57 return [x,y,z]; 58 } 59 60 function project([x,y,z]) { // z is ignored 61 return [CX + x*SCALE, CY - y*SCALE]; 62 } 63 64 /* ---------- main draw loop ---------- */ 65 function draw(tMillis){ 66 const t = tMillis * 0.001; // seconds 67 const yaw = 0.5*0.7 * t; 68 const pitch = 0.5*0.3 * t; 69 const roll = 0.5*0.5 * t; 70 71 // clear 72 ctx.clearRect(0,0,W,H); 73 74 // project all vertices for this frame 75 const screen = VERTS.map(v => project(rotate(v, yaw, pitch, roll))); 76 77 /* draw black vertex disks first */ 78 ctx.fillStyle = '#000'; 79 screen.forEach(([x,y])=>{ 80 ctx.beginPath(); 81 ctx.arc(x, y, DISK_RADIUS, 0, Math.PI*2); 82 ctx.fill(); 83 }); 84 85 /* draw thick white edges on top */ 86 ctx.lineWidth = EDGE_THICK; 87 ctx.strokeStyle = '#fff'; // same as background 88 ctx.lineCap = 'round'; 89 ctx.beginPath(); 90 EDGES.forEach(([i,j])=>{ 91 const [x1,y1] = screen[i]; 92 const [x2,y2] = screen[j]; 93 ctx.moveTo(x1,y1); 94 ctx.lineTo(x2,y2); 95 }); 96 ctx.stroke(); 97 98 requestAnimationFrame(draw); 99 } 100 requestAnimationFrame(draw); 101})(); 102</script> 103</body> 104</html>