基于css3的3D场景 c3d.js
应用与实现

Created by @dongtianee / Powered by reveal.js

浏览器中实现3D效果

有哪些可利用的技术?

alteredqualia.com

目前,CSS可能是在浏览器中绘制3D场景代价最小,成本最低,兼容最好的一种技术手段了。

当然效果也一般,今天重点就聊聊她。

SEC 1. 说说CSS3的transform

大家平时都在用哪些值?

transfrom 复习

translate3d

rotateX

rotateY

rotateZ

scale3d

transform-style

transform-origin

perspective

transform

我们来造1个3d场景

    
        html{transform-style:preserve-3d;perspective:1000px;}
        body{transition:transform 1.5s ease-in;transform:translate3d(0,-600px,100px) rotateX(30deg)}
    
             

DEMO

一个基于css的

3D场景库

c3d.js

Sec 1. 效果

成品

效果1

效果2

效果3(缘起)

Sec 2. C3D.js的基本方法

1.1 简单平面 / 新建一个平面

                 
    //新建一个3d主场景,存放其它3D元素。
    var s = new C3D.Stage();
    s.size(window.innerWidth, window.innerHeight).material({
    color: "#ddd"
    }).update();

    //将场景放在指定位置。不一定非是body
    document.body.appendChild(s.el);

    //创建1个平面放入场景
    //可以为平面设置很多属性,例如位置,旋转角度,背景图片,背景色,透明度。
    //平面本身是一个div,可以为其设置class和id。
    var p = new C3D.Plane();
    p.name('ppp').size(100).position(0, 0, -s.fov).rotation(0, 0, 0).material({
    color: C3D.getRandomColor(),
    image: 'images/mouse.jpg'
    }).filter({blur: ['5px'], brightness: [3]}).class('abg').id('bbb').update();
    s.addChild(p);
                
             

DEMO

1.2 简单平面 / 将现有元素放在3d场景

                 
    <div id="animationDiv" class="animation">一个div,拥有动效和复杂交互事件。</div>
                    
                    
    //新建一个3d主场景,存放其它3D元素。
    var s = new C3D.Stage();
    document.body.appendChild(s.el);

    //将现有的元素放入3d场景中。
    var p = new C3D.Plane({el:'<div class="sd" id="myDiv">我是一个div</div>'});
    //or
    var pp = new C3D.Plane({el:document.getElementById('animationDiv')});
    p.name('ppp').position(0, 0, -s.fov).rotation(0, 0, 0).update();
    s.addChild(p);
                 
             

2. 方块儿 Box与SkyBox

                
    //新建一个3d主场景,存放其它3D元素。
    var s = new C3D.Stage();
    document.body.appendChild(s.el);

    //与平面相比,具有back,font,left,right,up,down6个属性。
    //将6个面看作6个Plane,可分别设置他们的属性
    var c = new C3D.Box();

    //SkyBox与Box的区别是,UpdateS刷新方式不同
    var cc = new C3D.Skybox();
    cc.size(1024).position(0, 0, 0).material({
        front: {image: "images/cube_FR.jpg"},
        back: {image: "images/cube_BK.jpg"},
        left: {image: "images/cube_LF.jpg"},
        right: {image: "images/cube_RT.jpg"},
        up: {image: "images/cube_UP.jpg"},
        down: {image: "images/cube_DN.jpg"}
    }).update();

    s.addChild(cc);

                
             

DEMO

* 使用1个函数创建场景

                
    //新建一个3d主场景,存放其它3D元素。
    var s = new C3D.Stage();
    document.body.appendChild(s.el);

    var scene = C3D.create({
    type: 'sprite', position: [0, 0, -s.fov], children: [
        {
            type: 'plane',
            el: document.getElementById('mouse'),
            name: 'p1',
            size: [100],
            position: [100, 0, 0],
            rotation: [45, 0, 0],
            material: [{color: C3D.getRandomColor()}]
        },
        {},
        {}
    ]
    });

    s.addChild(scene);
                
             

DEMO

然后就没有了。

c3d库做的3件事情:

1.构造了1个3维空间作为容器,可以对空间进行transfrom

2.构造了1个平面,可以被放置在3维空间中任意位置,可以对平面进行transform

3.依据平面,简单封装了一个正方形盒子,可以对盒子进行transform

但是,有了这几个函数,就可以做很多事情了。

比如一些动画,一些交互。

我们可以自己写函数,让场景或场景内元素 动起来

                
    //自动运动
    function go() {
        scene.rotate(0, 1, 0).updateT(); //增量旋转
        scene.p1.rotate(-1, 0, 0).updateT();
        requestAnimationFrame(go);
    }

    requestAnimationFrame(go);

    //手动运动
    //通过监听touch事件,响应旋转与移动
                
             

运动的平面

运动的SkyBox

我们可以自己写函数,构建一个3D环形场景。

    
        //老规矩,创建一个容器s,略过
        //创建20个小平面,一个挨一个组成一张大平面。
        var panoRect = {w: 2586, h: 1170}; //大平面的高宽
        var _len = 20;
        var _width = panoRect.w / _len;
        var _radius = Math.floor(_step / 2 / Math.tan(Math.PI / _len));

        var sp = new C3D.Sprite();//大平面容器
        for (var i = 0; i < _len; i++) {
            var _p = new C3D.Plane();
            var _r = 360 / _len * i;
            var _a = Math.PI * 2 / _len * i;
            _p.size(_width, panoRect.h).position(Math.sin(_a) * _radius, 0, -Math.cos(_a) * _radius).rotation(0, -_r, 0).material({
            color:C3D.getRandomColor()
            }).update();
            sp.addChild(_p);
        }
        sp.position(0, 0, -400).updateT();
        s.addChild(sp);
        //监听touch事件,让场景随触摸运动。略。
    
             

DEMO

添加图片,鸟枪换炮

    
        //准备1张大图,切成20等份,作为20个小平面的背景图。
        var bgData = [
            {url: 'images/zwj/p1.png'},
            ...
        ];

        //设置plane的meterial:

        .meterial({
            image: imgs[i].url,
            repeat: 'no-repeat',
            bothsides: false
        });
    
             

DEMO

混合在一起的复杂场景

stage > sprite > plane/box/skybox

1个stage中放有多个sprite,每个sprite中有自己的box,或plane

混合DEMO

c3d.js简单剖析

还是刚才那张图

通过刚才的混合场景的例子,看看各个方法都做了什么事情。

混合DEMO

html5 设备方法

Camera API

The geolocation object

deviceorientation

devicemotion

Online and offline events

Fullscreen API

Gamepad

Battery Status

Notification

deviceorientation

    
        window.addEventListener("deviceorientation", function(event){
            var x = event.beta;  // In degree in the range [-180,180]
            var y = event.gamma; // In degree in the range [-90,90]
        });
    
             

总结

c3d.js在小型3d场景构建上还是非常好用的,适合一些活动界面开发。

今天的分享不指望大家会用它,因为我也是略知一二 >_< 。

只要

知道有一个可以css3构建3d场景的库

复习了一些transform值

知道html5的一些设备方法

THE END

谢谢大家!