# 3D Canvas in HTML5

## Creating a 3D Canvas Hexagon in HTML5

In this article, we will learn how to create a 3D object in HTML5. In this article, we will learn how to make a hexagon that will rotate around its axis.

Before creating our own 3D engine, we should first understand how the illusion of 3D space is created on a 2D screen. These illusions are called 3D projections. 3D projections map points onto a two-dimensional plane. In our case, the three-dimensional points define an object we wish to render, and the two-dimensional plane is the computer screen.

If we are defining the rotation of the plane with an angle, theta, the 3D projection calculations suddenly become quite simple! Any point on our three-dimensional plane can be defined with the following two equations that describe a point along the edges of an ellipse: x = A * cos(theta) y = B * sin(theta)

where A is half of the ellipse width, and B is half of the ellipse height.

We do all this in JavaScript. In this we first draw the front bottom of the Hexagon with the following:
1. c.beginPath();
2. c.moveTo(myShape.centerPlane.topLeftX, myShape.centerPlane.topLeftY); // top left
3. c.lineTo(myShape.centerPlane.topRightX, myShape.centerPlane.topRightY); // top right
4. c.lineTo(myShape.bottomPlane.topRightX, myShape.bottomPlane.topRightY); // bottom right
5. c.lineTo(myShape.bottomPlane.topLeftX, myShape.bottomPlane.topLeftY); // bottom left
6. c.closePath();
7.
8. c.lineJoin = "round";
9. c.strokeStyle = "black";
10. c.lineWidth = lineWidth;
11. c.stroke();
12. c.fillStyle = "blue";
13. c.fill();
Then we draw the back bottom of the Hexagon with the following:
1. c.beginPath();
2. c.moveTo(myShape.centerPlane.bottomLeftX, myShape.centerPlane.bottomLeftY); // top left
3. c.lineTo(myShape.centerPlane.bottomRightX, myShape.centerPlane.bottomRightY); // top right
4. c.lineTo(myShape.bottomPlane.bottomRightX, myShape.bottomPlane.bottomRightY); // bottom right
5. c.lineTo(myShape.bottomPlane.bottomLeftX, myShape.bottomPlane.bottomLeftY); // bottom left
6. c.closePath();
7.
8. c.lineJoin = "round";
9. c.strokeStyle = "black";
10. c.lineWidth = lineWidth;
11. c.stroke();
12. c.fillStyle = "blue";
13. c.fill();
After that  we draw the front top of the Hexagon with the following:
1. c.beginPath();
2. c.moveTo(myShape.topPlane.topLeftX, myShape.topPlane.topLeftY); // top left
3. c.lineTo(myShape.topPlane.topRightX, myShape.topPlane.topRightY); // top right
4. c.lineTo(myShape.centerPlane.topRightX, myShape.centerPlane.topRightY); // bottom right
5. c.lineTo(myShape.centerPlane.topLeftX, myShape.centerPlane.topLeftY); // bottom left
6. c.closePath();
7.
8. c.lineJoin = "round";
9. c.strokeStyle = "black";
10. c.lineWidth = lineWidth;
11. c.stroke();
12. c.fillStyle = "green";
13. c.fill();
Then we draw the back top of the Hexagon with the following:
1. c.beginPath();
2. c.moveTo(myShape.topPlane.bottomLeftX, myShape.topPlane.bottomLeftY); // top left
3. c.lineTo(myShape.topPlane.bottomRightX, myShape.topPlane.bottomRightY); // top right
4. c.lineTo(myShape.centerPlane.bottomRightX, myShape.centerPlane.bottomRightY); // bottom right
5. c.lineTo(myShape.centerPlane.bottomLeftX, myShape.centerPlane.bottomLeftY); // bottom left
6. c.closePath();
7.
8. c.lineJoin = "round";
9. c.strokeStyle = "black";
10. c.lineWidth = lineWidth;
11. c.stroke();
12. c.fillStyle = "blue";
13. c.fill();
Finally draw the top of the Hexagon with the following:
1. c.beginPath();
2. c.moveTo(myShape.topPlane.topLeftX, myShape.topPlane.topLeftY); // top left
3. c.lineTo(myShape.topPlane.topRightX, myShape.topPlane.topRightY); // top right
4. c.lineTo(myShape.topPlane.bottomRightX, myShape.topPlane.bottomRightY); // bottom right
5. c.lineTo(myShape.topPlane.bottomLeftX, myShape.topPlane.bottomLeftY); // bottom left
6. c.closePath();
7.
8. c.strokeStyle = "black";
9. c.lineWidth = lineWidth;
10. c.stroke();
11. c.fillStyle = "green";
12. c.fill();
Similarily we draw the left and right side of the hexagon.

We generate the hexagon and rotate it using the "generate()" and "rotate()" methods, as in the following:
1. function Shape(topPlane, centerPlane, bottomPlane)
2. {
3.     this.topPlane = topPlane;
4.     this.centerPlane = centerPlane;
5.     this.bottomPlane = bottomPlane;
6.
7.     this.rotate = function (newTheta)
8.     {
9.         topPlane.rotate(newTheta);
10.         centerPlane.rotate(newTheta);
11.         bottomPlane.rotate(newTheta);
12.     }
13.
14.     this.generatePlanes = function ()
15.     {
16.         topPlane.generate();
17.         centerPlane.generate();
18.         bottomPlane.generate();
19.     }
Example:
1. <!DOCTYPE html>
2.
3. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
5.     <meta charset="utf-8" />
6.     <title>ThreeD HTML5</title>
7.     <style>
8.         body {
9.             margin: 0px;
11.         }
12.
13.         #myCanvas
14.         {
15.             border: 1px solid black;
16.         }
17.     </style>
18.     <script>
19.         var canvas = null;
20.         var c = null;
21.         var canvasWidth = 576;
22.         var canvasHeight = 400;
23.         var t = 0;
24.
25.         var myShape = null;
26.
27.         function Shape(topPlane, centerPlane, bottomPlane) {
28.             this.topPlane = topPlane;
29.             this.centerPlane = centerPlane;
30.             this.bottomPlane = bottomPlane;
31.
32.             this.rotate = function (newTheta) {
33.                 topPlane.rotate(newTheta);
34.                 centerPlane.rotate(newTheta);
35.                 bottomPlane.rotate(newTheta);
36.             }
37.
38.             this.generatePlanes = function () {
39.                 topPlane.generate();
40.                 centerPlane.generate();
41.                 bottomPlane.generate();
42.             }
43.         }
44.
45.         function Plane(centerX, centerY, planeLength, planeWidth, planeTilt, planeTheta) {
46.             this.centerX = centerX;
47.             this.centerY = centerY;
48.             this.planeLength = planeLength;
49.             this.planeTheta = planeTheta;
50.
51.             var lastPerspectiveX = null;
52.             var lastPerspectiveX2 = null;
53.             var planeNextCornerAngle = 2 * Math.asin(planeWidth / planeLength);
54.
55.             this.rotate = function (newTheta) {
56.                 planeTheta = newTheta - planeNextCornerAngle / 2;
57.             }
58.
59.             this.translate = function (newCenterX, newCenterY) {
60.                 centerX = newCenterX;
61.                 centerY = newCenterY;
62.             }
63.
64.             this.generate = function () {
65.                 var ovalLength = planeLength;
66.                 var ovalWidth = ovalLength * planeTilt;
67.
68.                 var perspectiveX = (ovalLength / 2) * Math.cos(planeTheta);
69.                 var perspectiveY = (ovalWidth / 2) * Math.sin(planeTheta);
70.                 var perspectiveX2 = (ovalLength / 2) * Math.cos(planeTheta + planeNextCornerAngle);
71.                 var perspectiveY2 = (ovalWidth / 2) * Math.sin(planeTheta + planeNextCornerAngle);
72.
73.                 this.topLeftX = (perspectiveX * 1) + centerX;
74.                 this.topLeftY = (perspectiveY * -1) + centerY;
75.                 this.bottomRightX = (perspectiveX * -1) + centerX;
76.                 this.bottomRightY = (perspectiveY * 1) + centerY
77.                 this.topRightX = (perspectiveX2 * 1) + centerX;
78.                 this.topRightY = (perspectiveY2 * -1) + centerY;
79.                 this.bottomLeftX = (perspectiveX2 * -1) + centerX;
80.                 this.bottomLeftY = (perspectiveY2 * 1) + centerY;
81.             }
82.         }
83.
84.         function clearCanvas() {
85.             canvas.width = 1;
86.             canvas.width = canvasWidth;
87.         }
88.
89.         function init() {
90.             canvas = document.getElementById("myCanvas");
91.             c = canvas.getContext("2d");
92.             canvas.width = canvasWidth;
93.             canvas.height = canvasHeight;
94.
95.             var topPlane = new Plane(288, 150, 100, 70, 0.5, theta);
96.             var centerPlane = new Plane(288, 200, 600, 70, 0.5, theta);
97.             var bottomPlane = new Plane(288, 250, 100, 70, 0.5, theta);
98.
99.             myShape = new Shape(topPlane, centerPlane, bottomPlane);
100.
101.             //drawScreen();
102.
104.         }
105.
106.         var theta = 0; // top left
107.         function drawScreen() {
108.
109.             var lineWidth = 2;
110.
111.             myShape.rotate(theta);
112.             //myPlane.translate(tankX, 100);
113.             myShape.generatePlanes();
114.
115.             // draw front bottom of Hexagon
116.             c.beginPath();
117.             c.moveTo(myShape.centerPlane.topLeftX, myShape.centerPlane.topLeftY); // top left
118.             c.lineTo(myShape.centerPlane.topRightX, myShape.centerPlane.topRightY); // top right
119.             c.lineTo(myShape.bottomPlane.topRightX, myShape.bottomPlane.topRightY); // bottom right
120.             c.lineTo(myShape.bottomPlane.topLeftX, myShape.bottomPlane.topLeftY); // bottom left
121.             c.closePath();
122.
123.             c.lineJoin = "round";
124.             c.strokeStyle = "black";
125.             c.lineWidth = lineWidth;
126.             c.stroke();
127.             c.fillStyle = "blue";
128.             c.fill();
129.
130.             // draw back bottom of Hexagon
131.             c.beginPath();
132.             c.moveTo(myShape.centerPlane.bottomLeftX, myShape.centerPlane.bottomLeftY); // top left
133.             c.lineTo(myShape.centerPlane.bottomRightX, myShape.centerPlane.bottomRightY); // top right
134.             c.lineTo(myShape.bottomPlane.bottomRightX, myShape.bottomPlane.bottomRightY); // bottom right
135.             c.lineTo(myShape.bottomPlane.bottomLeftX, myShape.bottomPlane.bottomLeftY); // bottom left
136.             c.closePath();
137.
138.             c.lineJoin = "round";
139.             c.strokeStyle = "black";
140.             c.lineWidth = lineWidth;
141.             c.stroke();
142.             c.fillStyle = "blue";
143.             c.fill();
144.
145.             // draw front top of Hexagon
146.             c.beginPath();
147.             c.moveTo(myShape.topPlane.topLeftX, myShape.topPlane.topLeftY); // top left
148.             c.lineTo(myShape.topPlane.topRightX, myShape.topPlane.topRightY); // top right
149.             c.lineTo(myShape.centerPlane.topRightX, myShape.centerPlane.topRightY); // bottom right
150.             c.lineTo(myShape.centerPlane.topLeftX, myShape.centerPlane.topLeftY); // bottom left
151.             c.closePath();
152.
153.             c.lineJoin = "round";
154.             c.strokeStyle = "black";
155.             c.lineWidth = lineWidth;
156.             c.stroke();
157.             c.fillStyle = "green";
158.             c.fill();
159.
160.             // draw back top of Hexagon
161.             c.beginPath();
162.             c.moveTo(myShape.topPlane.bottomLeftX, myShape.topPlane.bottomLeftY); // top left
163.             c.lineTo(myShape.topPlane.bottomRightX, myShape.topPlane.bottomRightY); // top right
164.             c.lineTo(myShape.centerPlane.bottomRightX, myShape.centerPlane.bottomRightY); // bottom right
165.             c.lineTo(myShape.centerPlane.bottomLeftX, myShape.centerPlane.bottomLeftY); // bottom left
166.             c.closePath();
167.
168.             c.lineJoin = "round";
169.             c.strokeStyle = "black";
170.             c.lineWidth = lineWidth;
171.             c.stroke();
172.             c.fillStyle = "blue";
173.             c.fill();
174.
175.             // draw top of Hexagon
176.             c.beginPath();
177.             c.moveTo(myShape.topPlane.topLeftX, myShape.topPlane.topLeftY); // top left
178.             c.lineTo(myShape.topPlane.topRightX, myShape.topPlane.topRightY); // top right
179.             c.lineTo(myShape.topPlane.bottomRightX, myShape.topPlane.bottomRightY); // bottom right
180.             c.lineTo(myShape.topPlane.bottomLeftX, myShape.topPlane.bottomLeftY); // bottom left
181.             c.closePath();
182.
183.             c.strokeStyle = "black";
184.             c.lineWidth = lineWidth;
185.             c.stroke();
186.             c.fillStyle = "green";
187.             c.fill();
188.
189.             if (isRightSideOfShapeInFront(myShape)) {
190.                 // draw right of Hexagon
191.                 c.beginPath();
192.                 c.moveTo(myShape.topPlane.topRightX, myShape.topPlane.topRightY); // front
193.                 c.lineTo(myShape.centerPlane.topRightX, myShape.centerPlane.topRightY); // front
194.                 c.lineTo(myShape.bottomPlane.topRightX, myShape.bottomPlane.topRightY); // front
195.                 c.lineTo(myShape.bottomPlane.bottomRightX, myShape.bottomPlane.bottomRightY); // back
196.                 c.lineTo(myShape.centerPlane.bottomRightX, myShape.centerPlane.bottomRightY); // back
197.                 c.lineTo(myShape.topPlane.bottomRightX, myShape.topPlane.bottomRightY); // back
198.                 c.closePath();
199.
200.                 c.strokeStyle = "black";
201.                 c.lineWidth = lineWidth;
202.                 c.stroke();
203.                 c.fillStyle = "red";
204.                 c.fill();
205.             }
206.             else {
207.                 // draw left of Hexagon
208.                 c.beginPath();
209.                 c.moveTo(myShape.topPlane.topLeftX, myShape.topPlane.topLeftY); // front
210.                 c.lineTo(myShape.centerPlane.topLeftX, myShape.centerPlane.topLeftY); // front
211.                 c.lineTo(myShape.bottomPlane.topLeftX, myShape.bottomPlane.topLeftY); // front
212.                 c.lineTo(myShape.bottomPlane.bottomLeftX, myShape.bottomPlane.bottomLeftY); // back
213.                 c.lineTo(myShape.centerPlane.bottomLeftX, myShape.centerPlane.bottomLeftY); // back
214.                 c.lineTo(myShape.topPlane.bottomLeftX, myShape.topPlane.bottomLeftY); // back
215.                 c.closePath();
216.
217.                 c.strokeStyle = "black";
218.                 c.lineWidth = lineWidth;
219.                 c.stroke();
220.                 c.fillStyle = "red";
221.                 c.fill();
222.             }
223.
224.         }
225.
226.         function isRightSideOfShapeInFront(tankObj) {
227.             if (tankObj.topPlane.topRightY > tankObj.topPlane.topLeftY) {
228.                 return true;
229.             }
230.             else {
231.                 return false;
232.             }
233.         }
234.
236.             theta += .01; // radians
237.             clearCanvas();
238.             drawScreen();
240.         }
241.
242.         function handleMouseDown(e) {
243.             var mouseX = e.clientX;
244.             var mouseY = e.clientY;
245.         }
246.
247.         function handleMouseMove(e) {
248.             var mouseX = e.clientX;
249.             var mouseY = e.clientY;
250.         }
251.
252.         function handleMouseUp(e) {
253.
254.         }
255.
256.     </script>