HTML5 3D Cube Slideshow

转载 2012年03月30日 09:24:00

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.

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!

Related Articles

Creating a 3D Animated Box HTML5 WebGL Photo Slideshow

Creating a 3D Animated Box HTML5 WebGL Photo Slideshow

HTML5 Canvas Slideshow

HTML5 Canvas Slideshow

HTML5 canvas – Custom brush (BezierCurveBrush)

android 3D系列之入门实践篇

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

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

猫猫分享,必须精品原创文章,欢迎转载。转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码素材地址:效果:代码...
  • u013357243
  • u013357243
  • 2015年05月08日 18:04
  • 2497

[译]伸缩立方(Scale Cube)

摘要: 本文翻译自http://microservices.io/articles/scalecube.html,作者Chris Richardson。这篇文章描述了伸缩应用的三个维度:X轴的伸缩...
  • Tivon_1
  • Tivon_1
  • 2018年01月27日 18:51
  • 11

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

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

android opengl 绘制立方体【转】

感觉opengl es还是很有用的,这几天一直在潜心研究。让人最琢磨不透的是Openg es中的定点变换流程,我这里先讲解下。 大家觉得好的,就顶一下,觉得不好的也别拍砖,出来混都挺不容易的哈   ...
  • zh0621
  • zh0621
  • 2011年11月07日 21:39
  • 1145

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

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

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

利用HTML5来实现3D效果,已经有无数的案例了,但是要利用HTML5做出像样的可视化3D建模设计系统却不是那么容易,所以这类产品非常少。 这里分享2个比较成熟的HTML5可视化3D建模设计系统。...
  • cuixiping
  • cuixiping
  • 2013年09月24日 13:54
  • 7497

html5伪3d游戏探索

前言现在微信推广上面可是有很多小游戏的,譬如,围住神经猫,最强眼力,连连看,消消看,也有一些2d跑酷类的。 但是一个问题在于,html5游戏没有3d出来,或者说,html5的3d技术不被所有浏览器支...
  • cdnight
  • cdnight
  • 2016年02月16日 16:33
  • 1021

伸缩立方(Scale Cube)

在这个模型中,通过在负载均衡器之后运行多份拷贝来伸缩应用的方式叫做X轴伸缩。另外两种伸缩方式叫Y轴伸缩和Z轴伸缩。微服务架构是Y轴伸缩的,让我们也同时认识下X轴和Z轴伸缩。 X轴伸缩 ...
  • sunhuiliang85
  • sunhuiliang85
  • 2016年10月21日 14:01
  • 1182

基于 HTML5 的 WebGL 技术构建 3D 场景(一)

HT for Web 提供了多种基础类型供用户建模使用,不同于传统的 3D 建模方式,HT 的建模核心都是基于 API 的接口方式,通过 HT 预定义的图元类型和参数接口,进行设置达到三维模型的构建。...
  • u013161495
  • u013161495
  • 2016年07月13日 00:51
  • 5814
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HTML5 3D Cube Slideshow
举报原因:
原因补充:

(最多只允许输入30个字)