# HTML5 3D Cube Slideshow

HTML5 3D Cube Slideshow

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>
<h2>HTML5 3D Cube Slideshow</h2>
<a href="http://www.script-tutorials.com/html5-3d-cube-slideshow/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
<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);
}


At the first, I have defined all vertices and faces (walls) of our virtual cube. Then I have defined rules of rotating. After – the most difficult thing – transformation of images with using ‘clip’ and ‘transform’.

### Conclusion

I hope that today’s 3D html5 cube lesson has been interesting for you. We have done another one nice html5 example. I will be glad to see your thanks and comments. Good luck!

• 本文已收录于以下专栏：

## android 3D系列之入门实践篇

By 何明桂（http://blog.csdn.net/hmg25） 转载请注明出处     通过之前文章--概念篇的学习，我们今天编写一个简单的入门程序，实现一个不断绕x轴，y轴旋转的彩色立方体，...
• hmg25
• 2011年09月01日 14:49
• 10629

## 猫猫学IOS（四十一）UI之核心动画 两行代码搞定3D转场（做android的哭死）

• u013357243
• 2015年05月08日 18:04
• 2497

## [译]伸缩立方(Scale Cube)

• Tivon_1
• 2018年01月27日 18:51
• 11

## 数百个 HTML5 例子学习 HT 图形组件 – 3D 建模篇

《数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇》里提到 HT 很多情况下不需要借助 3Ds Max 和 Blender 等专业 3D 建模工具也能做出很多效果，例如 3D 电...
• u013161495
• 2016年09月30日 09:44
• 1816

## android opengl 绘制立方体【转】

• zh0621
• 2011年11月07日 21:39
• 1145

## 基于HTML5实现3D监控应用流动效果

Hightopo的HT for Web作为3D客户端呈现解决方案，今天介绍的重点不在于采集这些指标，而在于如何应用HT的预定于3D元素来实现流动的效果。在《透过WebGL 3D看动画Easing函数本...
• u013161495
• 2015年10月11日 22:08
• 1405

## 2个比较成熟的HTML5可视化3D建模设计系统

• cuixiping
• 2013年09月24日 13:54
• 7497

## html5伪3d游戏探索

• cdnight
• 2016年02月16日 16:33
• 1021

## 伸缩立方(Scale Cube)

• sunhuiliang85
• 2016年10月21日 14:01
• 1182

## 基于 HTML5 的 WebGL 技术构建 3D 场景（一）

HT for Web 提供了多种基础类型供用户建模使用，不同于传统的 3D 建模方式，HT 的建模核心都是基于 API 的接口方式，通过 HT 预定义的图元类型和参数接口，进行设置达到三维模型的构建。...
• u013161495
• 2016年07月13日 00:51
• 5814

举报原因： 您举报文章：HTML5 3D Cube Slideshow 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)