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.
Here are our demo and downloadable package:
Live Demo
download in package
Ok, download the source files and lets start coding !
Step 1. HTML
This is markup of our result slideshow page. Here it is.
index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 3D Cube Slideshow | Script Tutorials</title>
<link href="css/main.css" rel="stylesheet" type="text/css" />
<script src="js/script.js"></script>
</head>
<body>
<header>
<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>
</header>
<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
cosa = Math.cos(rad)
sina = Math.sin(rad)
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
cosa = Math.cos(rad)
sina = Math.sin(rad)
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
cosa = Math.cos(rad)
sina = Math.sin(rad)
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);
oImg.onload = function () {
textureWidth = oImg.width;
textureHeight = oImg.height;
}
}
window.onload = function(){
// 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’.
Live Demo
download in package
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!
本教程展示了如何使用HTML5创建一个包含图片的旋转3D立方体幻灯片,提供了实时演示和源代码下载。



5285

被折叠的 条评论
为什么被折叠?



