## 3D Cube images Slideshow with HTML5

about a year ago   40962   7264
##### 98

Our new tutorial tells us about creation of animated 3D Cube slideshow (pictures are located within the walls of the cube). The cube itself rotates continuously.

### Step 1. HTML

This is markup of our result slideshow page. Here it is.

#### index.html

```<!DOCTYPE html>
<html lang="en" >
<meta charset="utf-8" />
<title>HTML5 3D Cube Slideshow | Script Tutorials</title>
<script src="js/script.js"></script>
<body>
<canvas id="slideshow" width="1280" height="800"></canvas>
</body>
</html>
```

### Step 2. CSS

#### css/main.css

That file available in package (because it just contains styles of page layout)

### Step 3. JS

#### js/script.js

```var canvas, ctx;
var aImages = [];
var points = [];
var triangles = [];
var textureWidth, textureHeight;
var lev = 3;
var angle = 0;

// scene vertices
var vertices = [
new Point3D(-2,-1,2),
new Point3D(2,-1,2),
new Point3D(2,1,2),
new Point3D(-2,1,2),
new Point3D(-2,-1,-2),
new Point3D(2,-1,-2),
new Point3D(2,1,-2),
new Point3D(-2,1,-2)
];

// scene faces (6 faces)
var faces  = [[0,1,2,3],[1,5,6,2],[5,4,7,6],[4,0,3,7],[0,4,5,1],[3,2,6,7]];

function Point3D(x,y,z) {
this.x = x;
this.y = y;
this.z = z;

this.rotateX = function(angle) {
var rad, cosa, sina, y, z
rad = angle * Math.PI / 180
y = this.y * cosa - this.z * sina
z = this.y * sina + this.z * cosa
return new Point3D(this.x, y, z)
}
this.rotateY = function(angle) {
var rad, cosa, sina, x, z
rad = angle * Math.PI / 180
z = this.z * cosa - this.x * sina
x = this.z * sina + this.x * cosa
return new Point3D(x,this.y, z)
}
this.rotateZ = function(angle) {
var rad, cosa, sina, x, y
rad = angle * Math.PI / 180
x = this.x * cosa - this.y * sina
y = this.x * sina + this.y * cosa
return new Point3D(x, y, this.z)
}
this.projection = function(viewWidth, viewHeight, fov, viewDistance) {
var factor, x, y
factor = fov / (viewDistance + this.z)
x = this.x * factor + viewWidth / 2
y = this.y * factor + viewHeight / 2
return new Point3D(x, y, this.z)
}
}

// array of photos
var aImgs = [
'images/pic1.jpg',
'images/pic2.jpg',
'images/pic3.jpg',
'images/pic4.jpg'
];
for (var i = 0; i < aImgs.length; i++) {
var oImg = new Image();
oImg.src = aImgs[i];
aImages.push(oImg);

textureWidth = oImg.width;
textureHeight = oImg.height;
}
}

// creating canvas objects
canvas = document.getElementById('slideshow');
ctx = canvas.getContext('2d');

// prepare points
for (var i = 0; i <= lev; i++) {
for (var j = 0; j <= lev; j++) {
var tx = (i * (textureWidth / lev));
var ty = (j * (textureHeight / lev));
points.push({
tx: tx,
ty: ty,
nx: tx / textureWidth,
ny: ty / textureHeight,
ox: i,
oy: j
});
}
}

// prepare triangles ----
var levT = lev + 1;
for (var i = 0; i < lev; i++) {
for (var j = 0; j < lev; j++) {
triangles.push({
p0: points[j + i * levT],
p1: points[j + i * levT + 1],
p2: points[j + (i + 1) * levT],
up: true
});
triangles.push({
p0: points[j + (i + 1) * levT + 1],
p1: points[j + (i + 1) * levT],
p2: points[j + i * levT + 1],
up: false
});
}
}

drawScene();
};

function drawScene() {
// clear context
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

// rotate scene
var t = new Array();
for (var iv = 0; iv < vertices.length; iv++) {
var v = vertices[iv];
var r = v.rotateY(angle);
//var r = v.rotateX(angle).rotateY(angle);
var prj = r.projection(ctx.canvas.width, ctx.canvas.height, 1000, 3);
t.push(prj)
}

var avg_z = new Array();
for (var i = 0; i < faces.length; i++) {
var f = faces[i];
avg_z[i] = {"ind":i, "z":(t[f[0]].z + t[f[1]].z + t[f[2]].z + t[f[3]].z) / 4.0};
}

// get around through all faces
for (var i = 0; i < faces.length; i++) {
var f = faces[avg_z[i].ind];

if (t[f[3]].z+t[f[2]].z+t[f[1]].z+t[f[0]].z > -3) {
ctx.save();

// draw surfaces
ctx.fillStyle = "rgb(160,180,160)";
ctx.beginPath();
ctx.moveTo(t[f[0]].x,t[f[0]].y);
ctx.lineTo(t[f[1]].x,t[f[1]].y);
ctx.lineTo(t[f[2]].x,t[f[2]].y);
ctx.lineTo(t[f[3]].x,t[f[3]].y);
ctx.closePath();
ctx.fill();

// draw stretched images
if (i < 4) {
var ip = points.length;
while (--ip > -1) {
var p = points[ip];
var mx = t[f[0]].x + p.ny * (t[f[3]].x - t[f[0]].x);
var my = t[f[0]].y + p.ny * (t[f[3]].y - t[f[0]].y);
p.px = (mx + p.nx * (t[f[1]].x + p.ny * (t[f[2]].x - t[f[1]].x) - mx)) + p.ox;
p.py = (my + p.nx * (t[f[1]].y + p.ny * (t[f[2]].y - t[f[1]].y) - my)) + p.oy;
}

var n = triangles.length;
while (--n > -1) {
var tri = triangles[n];
var p0 = tri.p0;
var p1 = tri.p1;
var p2 = tri.p2;

var xc = (p0.px + p1.px + p2.px) / 3;
var yc = (p0.py + p1.py + p2.py) / 3;

ctx.save();
ctx.beginPath();
ctx.moveTo((1.05 * p0.px - xc * 0.05), (1.05 * p0.py - yc * 0.05));
ctx.lineTo((1.05 * p1.px - xc * 0.05), (1.05 * p1.py - yc * 0.05));
ctx.lineTo((1.05 * p2.px - xc * 0.05), (1.05 * p2.py - yc * 0.05));
ctx.closePath();
ctx.clip();

// transformation
var d = p0.tx * (p2.ty - p1.ty) - p1.tx * p2.ty + p2.tx * p1.ty + (p1.tx - p2.tx) * p0.ty;
ctx.transform(
-(p0.ty * (p2.px - p1.px) -  p1.ty * p2.px  + p2.ty *  p1.px + (p1.ty - p2.ty) * p0.px) / d, // m11
(p1.ty *  p2.py + p0.ty  * (p1.py - p2.py) - p2.ty *  p1.py + (p2.ty - p1.ty) * p0.py) / d, // m12
(p0.tx * (p2.px - p1.px) -  p1.tx * p2.px  + p2.tx *  p1.px + (p1.tx - p2.tx) * p0.px) / d, // m21
-(p1.tx *  p2.py + p0.tx  * (p1.py - p2.py) - p2.tx *  p1.py + (p2.tx - p1.tx) * p0.py) / d, // m22
(p0.tx * (p2.ty * p1.px  -  p1.ty * p2.px) + p0.ty * (p1.tx *  p2.px - p2.tx  * p1.px) + (p2.tx * p1.ty - p1.tx * p2.ty) * p0.px) / d, // dx
(p0.tx * (p2.ty * p1.py  -  p1.ty * p2.py) + p0.ty * (p1.tx *  p2.py - p2.tx  * p1.py) + (p2.tx * p1.ty - p1.tx * p2.ty) * p0.py) / d  // dy
);
ctx.drawImage(aImages[i], 0, 0);
ctx.restore();
}
}
}
}

// shift angle and redraw scene
angle += 0.3;
setTimeout(drawScene, 40);
}
```

The article source:http://www.script-tutorials.com/html5-3d-cube-slideshow/

Category