美文网首页IT在线课程Web前端之路让前端飞
闲聊js15: 动画、数学与碰撞检测1(css3 3D动画 与

闲聊js15: 动画、数学与碰撞检测1(css3 3D动画 与

作者: 随风而行之青衫磊落险峰行 | 来源:发表于2017-08-20 10:39 被阅读318次

    经历了十多篇的渲染器以及闲聊js: 实现一个关键的,最小化的,非场景图类型的精灵系统(上)闲聊js: 实现一个关键的,最小化的,非场景图类型的精灵系统(下),我们已经有了一个可以演示动画,数学,碰撞检测的小类库。今天是第一篇!

    先看gif吧:

    demo-0-12.gif
    1. 并行动画:物体一边放大,一边绕x轴(pitch,上下转)旋转,一边朝前方平移
    2. 达到要求的位置后,紧接着绕y轴(yaw,左右转)旋转一定角度
    3. 上述过程中,物体的表面显示绕z轴(roll,滚转)旋转的精灵和网格背景

    本篇目的:
    通过一个css 3D 动画 + BLFRender2D协同作战的Demo,来了解

    • 什么是动画(Animation)
    • 属性动画(Property Animation)
    • 动画按时间发生的顺序进行分类
    • css3对动画的支持
    • css3和BLFRender2D的对接
    • css3中 transition vs animation
    1. 什么是动画:

    按照opengl红宝书对动画的定义是: 重绘(repaint)+交换(swapBuffer)

    我个人来扩展一下对动画的定义是: 重复的【更新(update) + 重绘(repaint) + 交换(swapBuffer)】

    也就是我们BLFEngine2D中的run所做的事情

    run(msec) {
    
            //更新
            this.updateAll(msec);
            //重绘
            this.renderAll();
            
            //重复
            //调用requestAnimationFrame
            requestAnimationFrame((msec) => { this.run(msec) });
        }
    
    • update中,我们更新我们的位置,角度,缩放,颜色,alpha,.......一切可以变化的属性(例如ios/android中的属性动画)

    • repaint中进行绘图渲染,将渲染结果写入到后备缓冲区中

    • swapBuffer是指渲染后,提交显存显示
      这一步在浏览器中你看不到,因为浏览器(目前只要是绘图库,都是双缓存,最大的好处是避免闪烁)帮你做了这部操作。实际从底层来看,就是经典的双缓存bitblt【闲聊js:创建一个演示用的渲染库4(渲染表面,像素格式,光栅化,位块传输,图形与图像)】操作。如果是全屏独占模式(玩游戏都知道吧,我也不解释了),则仅仅是双显存缓冲区的指针交换,让前缓冲变为后缓存,后缓冲变为前缓冲,交替显示,速度超快(显示的同时,另外一个在渲染,玩过dx/gl的同学应该很了解这个机制)

    1. 属性动画:

    在我们的的精灵系统中,对精灵中的某个或某些属性进行更新和重绘。

    在css3/ios/android中都有属性动画概念,不了解的话,可以自己google/baidu一下

    1. 动画从时间来看,可以分为连续动画和并行动画两种类型:顺序动画(SequentialAnimation) / 并行动画(ParallelAnimation)
    • 顺序动画(SequentialAnimation): 表达的动作(Action)语义是:
      先...然后...最终....(很显然需前一个动作完成后,发出通知:我完成了,谁来继续下面的事情呢?)

    • 并行动画(ParallelAnimation): 表的的动作(Action)语义是:
      一边.....一边....(例如:物体一边扩大,一边旋转,一边平移)

    1. css3中对动画的支持:

    关于css3方面的内容,请自行参考上述文档。本篇不做详解

    1. css3和BLFRender2D的对接(css3代码来自与apple公司的flipcard demo,修改后用于我的demo)

    这些操作比较通用,就定义在BLFES6Lib.js中吧!

        //为了防止和jquery名字发生冲突,增加name后缀
       //例如jquery中是addClass,这里就变成了addClassName
    
        Element.prototype.hasClassName = function (a) {
            return new RegExp("(?:^|\\s+)" + a + "(?:\\s+|$)").test(this.className);
        };
    
        Element.prototype.addClassName = function (a) {
            if (!this.hasClassName(a)) {
                this.className = [this.className, a].join(" ");
            }
        };
    
        Element.prototype.removeClassName = function (b) {
            if (this.hasClassName(b)) {
                var a = this.className;
                this.className = a.replace(new RegExp("(?:^|\\s+)" + b + "(?:\\s+|$)", "g"), " ");
            }
        };
    
        Element.prototype.toggleClassName = function (a) {
            this[this.hasClassName(a) ? "removeClassName" : "addClassName"](a);
        };
         
        //上面代码都很简单,下面这个是加强版的函数
        Element.prototype.changeClassName = function(remove,add) {
            if(this.hasClassName(remove))
                this.removeClassName(remove);
            if(add)
                this.addClassName(add);
        }
    
    • 需求描述:
      1. 并行动画:物体一边放大,一边绕x轴(pitch,上下转)旋转,一边朝前方平移
      2. 达到要求的位置后,紧接着绕y轴(yaw,左右转)旋转一定角度
      3. 上述过程中,物体的表面显示绕z轴(roll,滚转)旋转的精灵和网格背景
      4. yaw/pitch/roll【欧拉角】来源于飞行器的姿态描述,在3D中用于描述物体的朝向,先暂时了解一下吧。其实很多基础知识,专业术语要了解,然后才能更精确的google/baidu,否则范围太广,搜索不到
    timg.jpg
    • css3动画:
            .container {
                width: 600px;
                height: 400x;
                margin: 0 auto 40px;
                border: 2px solid red;
                perspective: 1200px;
                /* 设置3D投影矩阵*/
            }
            
            @keyframes myTransform {
                from {
                    transform: translate3d(0px, 0px, -5000px) rotateX(-720deg);
                    /*从-720度*/
                }
                to {
                    transform: translate3d(0px, 0px, 0px) rotateX(720deg);
                    /*到720度*/
                }
            }
            
            @keyframes myYrotate {
                from {
                    transform: rotateY(0deg);
                }
                to {
                    transform: rotateY(720deg);
                }
            }
            
            /*并行动画*/
            .animation {
                width: 100%;
                height: 100%;
                transform-style: preserve-3d;
                /*使用3d变换*/
                animation: myTransform 5s;
            }
            
             /*顺序动画第二步*/
            .animation1 {
                width: 100%;
                height: 100%;
                transform-style: preserve-3d;
                /*使用3d变换*/
                animation: myYrotate 5s;
            }
    
    • html层次树及css3使用如下:
    <body>
        <h1>随风而行之青衫磊落险峰行 BLFRender2D + CSSAnimation3D Demo</h1>
    
        <section class="container">
            <canvas id="myCanvas" class="animation" width="600" height="400">
            你的浏览器还不支持哦
        </canvas>
        </section>
    </body>
    
    • js控制代码:
      var init = function() {
            let animationDiv = document.getElementById("myCanvas");
            //初始化时候,canvas上的动画使用的是上下旋转及向前平移(典型的并行动画),一旦完成后
            //触发webkitAnimationEnd事件
            //对webkitAnimationEnd事件进行处理,切换css为左右旋转,很典型的顺序动画
             //当完成一个动画序列后,浏览器会发送一个完成事件
            //我们对该事件进行处理就可以了animationDiv.addEventListener("webkitAnimationEnd", function() {
                animationDiv.changeClassName("animation", "animation1");
            }, false);
        };
    
        //挂接init事件处理函数
        window.addEventListener('DOMContentLoaded', init, false);
    
        let canvas = document.getElementById("myCanvas");
        let context = canvas.getContext('2d');
        let engine = new BLFEngine2D(context);
        let spr2 = new BLFDemoSprite(true);
        spr2.y = 200;
        spr2.rotateSpeed = -1; //逆时针
        engine.sprMgr.addSprite(new BLFGridSprite("background"));
        engine.sprMgr.addSprite(spr2);
        engine.run(); //run的是BLFSprite精灵系统的动画
    

    运行一下看效果:http://htmlpreview.github.io/?https://github.com/jackyblf/BLF_JS_Demos/blob/master/css3withBLFRender2D.html

    可能看不到效果,我也不知道为什么,也懒得花时间解决了

    大家可以到我的github上下载代码
    如果感觉不错,给我的github加颗小星星,鼓励鼓励我!

    对了,在使用css3中的animation/transition中遇到一些问题,然后查了一些资料结合实践,总结一下一起分享吧:

    1. transition简单易用,但是有如下几个缺点:
    1. 没法自动运行(init中),只能靠事件触发(例如click)
    2. 无法循环运行,只能一次结束
    3. 只能设置开始,结束状态,无中间任意多的过度状态设置
    4. 只能animate一个属性,例如设置了移动就不能旋转
      综上所述,transition全部的缺点就是animation的优点!

    相关文章

      网友评论

        本文标题:闲聊js15: 动画、数学与碰撞检测1(css3 3D动画 与

        本文链接:https://www.haomeiwen.com/subject/ldqtdxtx.html