'use strict'; // We will draw two pictures at once. // There will be one object and two of its projections var canvas1 = document.getElementById('canvas1'); var canvas2 = document.getElementById('canvas2'); var canvas_context1 = canvas1.getContext('2d'); var canvas_context2 = canvas2.getContext('2d'); // Move the origin of coordinates to the center of the block canvas_context1.translate(canvas1.width / 2, canvas1.height / 2); canvas_context2.translate(canvas2.width / 2, canvas2.height / 2); // The figure will be set as a combination of four planes. // Each plane is a combination of four points var arr_t = [ // Front face [{x:-100, y:-100, z:-100}, {x:100, y:-100, z:-100}, {x:100, y:100, z:-100}, {x:-100, y:100, z:-100}], // Right face [{x:100, y:-100, z:-100}, {x:100, y:-100, z:100}, {x:100, y:100, z:100}, {x:100, y:100, z:-100}], // Left face [{x:-100, y:-100, z:-100}, {x:-100, y:-100, z:100}, {x:-100, y:100, z:100}, {x:-100, y:100, z:-100}], // Rear face [{x:-100, y:-100, z:100}, {x:100, y:-100, z:100}, {x:100, y:100, z:100}, {x:-100, y:100, z:100}]]; // Center of the figure. // We'll make a turn around it var t0 = {x:0, y:0, z:0}; // Rotation angle in degrees var deg = 0; // For perspective projection: // Distance between the observer and the object. // Cannot be smaller than the size of the object, // in our case 200px var a = 300; // The size of the object on the screen in (%) var k = 70; // Current figure var arr_tt = []; for (var i = 0; i < arr_t.length; i++) { arr_tt[i] = arr_t[i].slice(); } // Current projection var arrProj; // Set the repaint screen function with the rotation of the figure. // Then this function will need to be inserted into the variable // window.onload function repaint() { // First, clear the screen - repaint with white color clearScreen(canvas1, canvas_context1, 'rgb(255,255,255)'); clearScreen(canvas2, canvas_context2, 'rgb(255,255,255)'); // Now turn the original figure by an angle on // the axis (Y) and overwrite the current figure for (var i = 0; i < arr_t.length; i++) { for (var j = 0; j < arr_t[0].length; j++) { arr_tt[i][j] = rotateByDegreeY(t0, arr_t[i][j], deg); } } // Get a parallel projection arrProj = getParallelProjection(arr_tt); // Draw a parallel projection canvas_context1.lineWidth = 2; // black translucent strokeFigure(canvas_context1, arrProj, 'rgba(0,0,0,0.5)'); // Get a perspective projection arrProj = getPerspectiveProjection(arr_tt); // Draw a perspective projection in a nearby window canvas_context2.lineWidth = 2; // black translucent strokeFigure(canvas_context2, arrProj, 'rgba(0,0,0,0.5)'); // Increase an angle deg += 1; } // Additional functions // Get a parallel projection of a figure on the screen plane function getParallelProjection(arr) { var arr_new = []; for (var i = 0; i < arr.length; i++) { arr_new[i] = []; for (var j = 0; j < arr[0].length; j++) { arr_new[i][j] = {}; arr_new[i][j].x = arr[i][j].x; arr_new[i][j].y = arr[i][j].y + arr[i][j].z / 4; } } return arr_new; } // Get a perspective projection function getPerspectiveProjection(arr) { var arr_new = []; for (var i = 0; i < arr.length; i++) { arr_new[i] = []; for (var j = 0; j < arr[0].length; j++) { arr_new[i][j] = {}; arr_new[i][j].x = (a / 100 * k) * arr[i][j].x / (arr[i][j].z + a); arr_new[i][j].y = (a / 100 * k) * arr[i][j].y / (arr[i][j].z + a); } } return arr_new; } // Fill the screen with the specified color function clearScreen(canvas, context, color) { context.fillStyle = color; context.beginPath(); context.fillRect(- canvas.width / 2, - canvas.height / 2, canvas.width, canvas.height); context.closePath(); context.fill(); } // Draw a figure through points from an array function strokeFigure(context, arr, color) { context.strokeStyle = color; context.fillStyle = color; for (var i = 0; i < arr.length; i++) { context.beginPath(); for (var j = 0; j < arr[0].length; j++) { if (j == 0) { context.moveTo(arr[i][j].x, arr[i][j].y); } else { context.lineTo(arr[i][j].x, arr[i][j].y); } } context.closePath(); context.stroke(); } } // Turn the point t(x,y,z) by an angle (deg) // on the axis (Y) relative to the point t0(x,y,z) function rotateByDegreeY(t0, t, deg) { var t_new = {}; // Translate the rotation angle from degrees to radians var rad = (Math.PI / 180) * deg; // Calculate the coordinates of the new point according to the formula t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.z-t0.z)*Math.sin(rad); t_new.y = t.y; t_new.z = t0.z+(t.x-t0.x)*Math.sin(rad)+(t.z-t0.z)*Math.cos(rad); // Return the received value return t_new; } // Set the screen repaint interval window.onload = function() { setInterval(repaint, 100); };