闲聊js15: 动画、数学与碰撞检测1(css3 3D动画 与 BLFEngine2D 协同作战)

经历了十多篇的渲染器以及闲聊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的优点!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 1,722评论 0 2
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,298评论 0 11
  • 看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印象,因...
    DCbryant阅读 1,853评论 0 4
  • 变形--旋转 rotate() 旋转rotate()函数通过指定的角度参数使元素相对原点进行旋转。它主要在二维空间...
    阿振_sc阅读 933评论 1 5
  • 我是255号星宝宝糕点女王小杨,正在参加日记星球21天蜕变第六期第9天。今天的日记是一个迷失的故事。 有一个商人...
    糕点女王小杨阅读 175评论 1 2