动画_动画渲染 - CSDN
  • 11 Animation动画

    千次阅读 2018-10-08 17:19:21
    这些天有些忙,导致一个...动画一般可以定义两种:一种是变形动画,另一种是骨骼动画。下面,我们先介绍一下变形动画。 变形动画 变形动画的实现就是通过修改当前模型的顶点位置来实现动画。就比如,一个动画...

    这些天有些忙,导致一个多星期没有更新文章,群里的小伙伴也天天催我更。为了表示歉意,我决定在现在的基础上面增加一节Three.js核心类的相关介绍,来让让小伙伴们能更清楚的了解相关的基础内容。下面我们开始这一节的内容,动画。
    动画一般可以定义两种:一种是变形动画,另一种是骨骼动画。下面,我们先介绍一下变形动画。

    变形动画

    变形动画的实现就是通过修改当前模型的顶点位置来实现动画。就比如,一个动画需要变动十次才可以实现,那么我们就需要为当前模型的每一个顶点定义每一次所在的位置,Three.js通过每一次修改实现最后的一个动画的整个流程。
    为了更好的理解变形动画,我们创建了一个案例,查看地址为:点击这里
    这个案例是为了让我们更好的了解变形动画的实现以及使用。在右上角,我们能发现两个可切换的拖拽条,这两个拖拽条对应的是两个变形目标数组,拖拽范围是0-1,就是当前的变形目标对本体的影响程度。我们进行拖拽就可以发现,界面中的立方体也会跟随着变动,影响当前的立方体。接下来我讲解一下,当前案例是如何实现的:

    • 首先,在我们创建模型的几何体时,给几何体morphTargets赋值了两个变形目标,morphTargets是一个数组,这意味着我们可以增加很多的变形目标,在给morphTargets添加的数组,我们需要自己定义一个名称和相关的顶点,这个顶点数据必须和默认的模型的顶点数据保持一致,设置完后,我们需要调用geometrycomputeMorphNormals()来更新:
    var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    
    // 创建两个影响立方体的变形目标
    var cubeTarget1 = new THREE.BoxGeometry(2, 10, 2);
    var cubeTarget2 = new THREE.BoxGeometry(8, 2, 8);
    
    // 将两个geometry的顶点放入到立方体的morphTargets里面
    cubeGeometry.morphTargets[0] = {name: 'target1', vertices: cubeTarget1.vertices};
    cubeGeometry.morphTargets[1] = {name: 'target2', vertices: cubeTarget2.vertices};
    cubeGeometry.computeMorphNormals();
    
    • 然后,当前模型使用的材质必须设置可以使用变形目标变形:
    var cubeMaterial = new THREE.MeshLambertMaterial({morphTargets: true, color: 0x00ffff});
    
    • 当我们创建好网格模型添加到场景内后,可以在mesh对象上面找到morphTargetInfluences这一个配置项,这里面也是一个数组,是和geometrymorphTargets相对应的,主要就是用于设置当前的变形目标对本体的影响度,默认值为0-1,0为不影响本体,1为完全影响本体:
    gui = {
        influence1:0.01,
        influence2:0.01,
        update : function () {
            cube.morphTargetInfluences[0] = gui.influence1;
            cube.morphTargetInfluences[1] = gui.influence2;
        }
    };
    

    通过上面我们手动实现了一个变形动画,就会发现,其实变形动画是一直在修改变形目标对本体的影响尺度。我们可以通过这个原理实现一些变形动画。
    当前案例代码查看地址:点击这里

    骨骼动画

    骨骼动画是需要生成一个与模型相关的骨架,骨架中的骨骼也会存在对应关系,模型的每一个需要动画的顶点需要设置影响它的骨骼以及骨骼影响顶点的程度。骨骼动画和变形动画相比会比较复杂一些,但是它又有更多的灵活性。我们可以想象一下人体的骨骼,如果使用变形动画,需要把所有的每一次的变动都存一个顶点数组,而骨骼动画,只需要设置骨骼的相关信息,就可以实现更多的动画。下面我们看一下骨骼动画的简单案例:点击这里
    skeleton
    这是一个官方提供的案例,我经过一些简单的修改,也将当前一个柱形图形的骨骼显示的出来,这个实现比较复杂,我们需要做的就是先理解它是怎么实现的:

    • 首先, 我们创建了一个圆柱几何体,然后通过圆柱的几何体每一个顶点的y轴坐标来设置需要绑定的骨骼的下标和影响的程度:
    //遍历几何体所有的顶点
    for (var i = 0; i < geometry.vertices.length; i++) {
    
        //根据顶点的位置计算出骨骼影响下标和权重
    
        var vertex = geometry.vertices[i];
        var y = (vertex.y + sizing.halfHeight);
    
        var skinIndex = Math.floor(y / sizing.segmentHeight);
        var skinWeight = (y % sizing.segmentHeight) / sizing.segmentHeight;
    
        geometry.skinIndices.push(new THREE.Vector4(skinIndex, skinIndex + 1, 0, 0));
        geometry.skinWeights.push(new THREE.Vector4(1 - skinWeight, skinWeight, 0, 0));
    
    }
    

    几何体的skinIndices属性和skinWeights属性就是来设置相关的绑定下标和权重(骨骼影响程度)。

    • 相应的,我们需要设置一组相关的骨骼,骨骼具有嵌套关系,这样才能实现一个骨架,由于圆柱体比较简单,我们就创建一条骨骼垂直嵌套的骨骼:
    bones = [];
    
    var prevBone = new THREE.Bone();
    bones.push(prevBone);
    prevBone.position.y = -sizing.halfHeight;
    
    for (var i = 0; i < sizing.segmentCount; i++) {
    
        var bone = new THREE.Bone();
        bone.position.y = sizing.segmentHeight;
        bones.push(bone); //添加到骨骼数组
        prevBone.add(bone); //上一个骨骼定义为父级
        prevBone = bone;
    
    }
    
    • 创建纹理时,我们还需要设置当前纹理需要受到骨骼的影响,将材质的skinning属性设置为true
    var lineMaterial = new THREE.MeshBasicMaterial({
        skinning: true,
        wireframe: true
    });
    
    • 最后,我们需要创建骨骼材质,并将模型绑定骨骼:
    mesh = new THREE.SkinnedMesh(geometry, [material, lineMaterial]);
    var skeleton = new THREE.Skeleton(bones); //创建骨架
    mesh.add(bones[0]); //将骨骼添加到模型里面
    mesh.bind(skeleton); //模型绑定骨架
    

    这样,我们就实现了使用Three.js创建一个简单的骨骼动画。使用dat.gui我们能够修改每一个骨骼的poisitionrotationscale并查看对当前模型的影响。案例的源码地址:点击这里

    两种动画的区别

    变形动画主要用于精度要求高的动画,比如人物的面部表情。优点是动画表达会很到位,缺点就是扩展性不强,只能执行设置好的相关动画。
    骨骼动画主要用于那种精度要求低,而且需要丰富多样的动画,就比如人物的走动,攻击防御等动画,我们可以通过一套骨骼,修改相应骨骼的位置的信息直接实现相应的效果。确定是没有变形动画的精度高,但是可以实现多种多样的效果。
    总结:我们可以根据项目的需求来设置不同的动画,就比如一个人物模型,说话我们使用变形动画去实现,而肢体动作使用骨骼动画去实现。

    导入模型动画

    Three.js的动画系统中,你可以为模型的各种属性设置动画:骨骼动画,变形动画,材质的相关属性(颜色,透明度, 是否可见)。动画属性可以设置淡入淡出效果以及各种扭曲特效。也可以单独的改变一个对象或者多个对象上的动画的影响程度和动画时间。
    为了实现这些,Three.js动画系统在2015年修改为了一个类似于Unity和虚幻引擎4的架构。接下来我们了解一下这套动画系统的主要组件以及它们时如何协同工作。

    动画片段(Animation Clips)

    在我们成功导入模型以后,如果模型拥有相关的动画属性,会在返回的模型数据中产生一个名为animations的数组,数组的每一个子项都是一个AnimationClips对象。
    每一个单独AnimationClips对象通常保存的都是模型的一个动画的数据,假如,如果模型网格是一个人物角色,第一个AnimationClips对象有可能保存的是人物走动的动画,第二个AnimationClips对象用于跳跃,第三个用于攻击动画等等。

    关键帧轨迹(Keyframe Tracks)

    AnimationClips对象内部,一般会有四个属性:

    • name:当前的动画的一个名称
    • uuid:一个不会重复的uuid
    • duration:当前动画一个循环所需要的时间
    • tracks:轨迹当前动画每一次切换动作所需要的数据

    假设当前的动画是骨骼动画,在关键帧轨迹中存储的数据是在每一帧骨骼随着时间变动的数据(位置,旋转和缩放等)。
    如果当前动画是一个变形动画,在关键帧轨迹中将会把顶点数据的变动存储在其中(比如实现人脸的笑以及哭等动作)。

    动画混合器(Animation Mixer)

    在动画片段中存储的数据仅仅构成了动画实现的基础,实际的播放权力在动画混合器的手中。你可以想象动画混合器其实不仅仅只是作为动画的播放器,它还可以同时控制几个动画,混合它们或者合并它们。

    动画播放器(Animation Actions)

    这个英文我更乐意将它翻译成动画播放器,因为我们最终需要将数据生成一个动画播放器来操作当前的动画执行,暂停或者停止,是否使用淡入淡出效果或者将动画加快或减慢。

    动画对象组(Animation Object Groups)

    如果你希望一组模型对象共享当前的动画,我们可以使用动画对象组来实现。

    通过导入模型显示动画

    变形动画

    变形动画

    我们首先查看一个官方的模型案例,这个案例效果是一匹马奔跑的动画,我们也可以通过下面地址查看:点击这里
    接下来我们看一下这匹马是如何实现的:

    • 在模型加载成功以后,我们首先将模型创建出来,并将材质的morphTargets设置为ture,可以使用变形动画:
    mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
        vertexColors: THREE.FaceColors,
        morphTargets: true
    }));
    mesh.castShadow = true;
    mesh.scale.set(0.1, 0.1, 0.1);
    scene.add(mesh);
    
    • 然后我们创建了一个针对于该模型的混合器:
    mixer = new THREE.AnimationMixer(mesh);
    
    • 接着使用变形目标数据创建一个动画片段:
    var clip = THREE.AnimationClip.CreateFromMorphTargetSequence('gallop', geometry.morphTargets, 30);
    
    • 使用混合器和动画片段创建一个动画播放器来播放:
    var action = mixer.clipAction(clip); //创建动画播放器
    action.setDuration(1); //设置当前动画一秒为一个周期
    action.play(); //设置当前动画播放
    
    • 最后,我们还需要在重新绘制循环中更新混合器,进行动作更新:
    function render() {
    
        control.update();
    
        var time = clock.getDelta();
    	//由于模型导入是异步的,所以我们再模型没有加载完之前是获取不到混合器的
        if (mixer) {
            mixer.update(time);
        }
    
        renderer.render(scene, camera);
    }
    

    骨骼动画

    骨骼动画

    骨骼动画模型我们使用的是gltf格式,这个模型是在Sketchfab网站下载,案例是一个小姐姐跳舞的一个片段,查看地址:点击这里
    gltf格式的模型导入进来以后,我们可以直接通过animations数组创建播放器:

    mixer = new THREE.AnimationMixer(obj); //通过当前模型创建混合器
    action = mixer.clipAction(gltf.animations[0]); //通过动画数据创建播放器
    

    直接调用播放器的播放事件让动画播放:

    action.play();
    

    最后,我们还是需要在循环渲染中更新混合器,并将每一帧渲染的间隔时间传入

    function render() {
        control.update();
        var time = clock.getDelta();
        if (mixer) {
            mixer.update(time);
        }
        renderer.render(scene, camera);
    }
    
    展开全文
  • HTML5实现动画三种方式

    千次阅读 2017-09-08 12:41:34
    HTML5实现动画三种方式

    编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是Canvas,还有css3和javascript.通过合理的选择,来实现最优的实现。

    PS:由于显卡、录制的帧间隔,以及可能你电脑处理器的原因,播放过程可能有些不太流畅或者失真!

    分三种方式实现:

    (1)   canvas元素结合JS

    (2)   纯粹的CSS3动画(暂不被所有主流浏览器支持,比如IE)

    (3)   CSS3结合Jquery实现

    知道如何使用CSS3动画比知道如何使用<canvas>元素更重要:因为浏览器能够优化那些元素的性能(通常是他们的样式,比如CSS),而我们使用canvas自定义画出来的效果却不能被优化。原因又在于,浏览器使用的硬件主要取决于显卡的能力。目前,浏览器没有给予我们直接访问显卡的权力,比如,每一个绘画操作都不得不在浏览器中先调用某些函数。

    1.canvas

    HTML代码:

    <html> 
    <head>
    <meta charset="UTF-8" />
    <title>Animation in HTML5 using the canvas element</title>
    </head>
    <body οnlοad="init();">
    <canvas id="canvas" width="1000" height="600">Your browser does not support the <code><canvas></code>-element.Please think about updating your brower!</canvas>
    <div id="controls">
    <button type="button" οnclick="speed(-0.1);">Slower</button>
    <button type="button" οnclick="play(this);">Play</button>
    <button type="button" οnclick="speed(+0.1)">Faster</button>
    </div>
    </body>
    </html>

    JS代码:

    定义一些变量:

    var dx=5,          //当前速率 
    rate=1, //当前播放速度
    ani, //当前动画循环
    c, //画图(Canvas Context)
    w, //汽车[隐藏的](Canvas Context)
    grassHeight=130, //背景高度
    carAlpha=0, //轮胎的旋转角度
    carX=-400, //x轴方向上汽车的位置(将被改变)
    carY=300, //y轴方向上汽车的位置(将保持为常量)
    carWidth=400, //汽车的宽度
    carHeight=130, //汽车的高度
    tiresDelta=15, //从一个轮胎到最接近的汽车底盘的距离
    axisDelta=20, //汽车底部底盘的轴与轮胎的距离
    radius=60; //轮胎的半径

    为了实例化汽车canvas(初始时被隐藏),我们使用下面的自执行的匿名函数

    (function(){ 
    var car=document.createElement('canvas'); //创建元素
    car.height=carHeight+axisDelta+radius; //设置高度
    car.width=carWidth; //设置宽度
    w=car.getContext('2d');
    })();

    点击“Play”按钮,通过定时重复执行“画汽车”操作,来模拟“帧播放”功能:

    function play(s){               //参数s是一个button 
    if(ani){ //如果ani不为null,则代表我们当前已经有了一个动画
    clearInterval(ani); //所以我们需要清除它(停止动画)
    ani=null;
    s.innerHTML='Play'; //重命名该按钮为“播放”
    }else{
    ani=setInterval(drawCanvas,40); //我们将设置动画为25fps[帧每秒],40/1000,即为二十五分之一
    s.innerHTML='Pause'; //重命名该按钮为“暂停”
    }
    }

    加速,减速,通过以下方法,改变移动距离的大小来实现:

    function speed(delta){ 
    var newRate=Math.max(rate+delta,0.1);
    dx=newRate/rate*dx;
    rate=newRate;
    }

    页面加载的初始化方法:

    //init 
    function init(){
    c=document.getElementById('canvas').getContext('2d');
    drawCanvas();
    }

    主调方法:

    function drawCanvas(){ 
    c.clearRect(0,0,c.canvas.width, c.canvas.height); //清除Canvas(已显示的),避免产生错误
    c.save(); //保存当前坐标值以及状态,对应的类似“push”操作

           drawGrass();                     //画背景
           c.translate(carX,0);                 //移动起点坐标
           drawCar();                       //画汽车(隐藏的canvas)
           c.drawImage(w.canvas,0,carY);            //画最终显示的汽车
           c.restore();                     //恢复Canvas的状态,对应的是类似“pop”操作
           carX+=dx;                        //重置汽车在X轴方向的位置,以模拟向前走
           carAlpha+=dx/radius;                 //按比例增加轮胎角度
    
           if(carX&gt;c.canvas.width){              //设置某些定期的边界条件
              carX=-carWidth-10;                //也可以将速度反向为dx*=-1;
           }
        }</pre><p>画背景:</p><pre class="javascript">function drawGrass(){
           //创建线性渐变,前两个参数为渐变开始点坐标,后两个为渐变结束点坐标
           var grad=c.createLinearGradient(0,c.canvas.height-grassHeight,0,c.canvas.height);
           //为线性渐变指定渐变色,0表示渐变起始色,1表示渐变终止色
           grad.addColorStop(0,'#33CC00');
           grad.addColorStop(1,'#66FF22');
           c.fillStyle=grad;
           c.lineWidth=0;
           c.fillRect(0,c.canvas.height-grassHeight,c.canvas.width,grassHeight);
    
        }</pre><p>画车身:</p><pre class="javascript">function drawCar(){
           w.clearRect(0,0,w.canvas.width,w.canvas.height);     //清空隐藏的画板
           w.strokeStyle='#FF6600';                 //设置边框色
           w.lineWidth=2;                       //设置边框的宽度,单位为像素
           w.fillStyle='#FF9900';                   //设置填充色
           w.beginPath();                       //开始绘制新路径
           w.rect(0,0,carWidth,carHeight);              //绘制一个矩形
           w.stroke();                          //画边框
           w.fill();                            //填充背景
           w.closePath();                       //关闭绘制的新路径
           drawTire(tiresDelta+radius,carHeight+axisDelta);     //我们开始画第一个轮子
           drawTire(carWidth-tiresDelta-radius,carHeight+axisDelta);    //同样的,第二个
    
        }</pre><p>画轮胎:</p><pre class="javascript">function drawTire(x,y){
           w.save();
           w.translate(x,y);
           w.rotate(carAlpha);
           w.strokeStyle='#3300FF';
           w.lineWidth=1;
           w.fillStyle='#0099FF';
           w.beginPath();
           w.arc(0,0,radius,0,2*Math.PI,false);
           w.fill();
           w.closePath();
           w.beginPath();
           w.moveTo(radius,0);
           w.lineTo(-radius,0);
           w.stroke();
           w.closePath();
           w.beginPath();
           w.moveTo(0,radius);
           w.lineTo(0,-radius);
           w.stroke();
           w.closePath();
           w.restore();
    
        }</pre><p>由于原理简单,并且代码中作了详细注释,这里就不一一讲解!</p><h3 id="t2"><a name="t2"></a><span style="font-size: 18px;">2.CSS3</span></h3><p><span style="font-size: 10px;">你将看到我们未通过一句JS代码就完全实现了和上面一样的动画效果:</span></p><p><span style="font-size: 10px;">HTML代码:</span></p><pre class="html">&lt;html&gt;
    

    <head>
    <meta charset=”UTF-8” />
    <title>Animations in HTML5 using CSS3 animations</title>
    </head>
    <body>
    <div id=”container”>
    <div id=”car”>
    <div id=”chassis”></div>
    <div id=”backtire” class=”tire”>
    <div class=”hr”></div>
    <div class=”vr”></div>
    </div>
    <div id=”fronttire” class=”tire”>
    <div class=”hr”></div>
    <div class=”vr”></div>
    </div>
    </div>
    <div id=”grass”></div>
    </div>
    <footer></footer>
    </body>
    </html>

    CSS代码:

     body 
    {
    padding:0;
    margin:0;
    }

    定义车身与轮胎转到的动画(你会看到基本每一个动画都有四个版本的定义:原生版本/webkit【Chrome|Safari】/ms【为了向后兼容IE10】/moz【FireFox】)

     /定义动画:从-400px的位置移动到1600px的位置 / 
    @keyframes carAnimation
    {
    0% { left:-400px; } /* 指定初始位置,0%等同于from*/
    100% { left:1600px; } /* 指定最终位置,100%等同于to*/
    }
     /* Safari and Chrome */
     @-webkit-keyframes carAnimation
     {
        0% {left:-400px; }
        100% {left:1600px; }
     }
    
     /* Firefox */
     @-moz-keyframes carAnimation
     {
        0% {left:-400; }
        100% {left:1600px; } 
     }
    
     /*IE暂不支持,此处定义是为了向后兼容IE10*/
     @-ms-keyframes carAnimation
     {
        0% {left:-400px; }
        100%{left:1600px; }
     }</pre><pre class="css" style="font-size: 10px;"> @keyframes tyreAnimation
     {
        0% {transform: rotate(0); }
        100% {transform: rotate(1800deg); }
     }
    
     @-webkit-keyframes tyreAnimation
     {
        0% { -webkit-transform: rotate(0); }
        100% { -webkit-transform: rotate(1800deg); }
     }
    
     @-moz-keyframes tyreAnimation
     {
        0% { -moz-transform: rotate(0); }
        100% { -moz-transform: rotate(1800deg); }
     }
    
     @-ms-keyframes tyreAnimation
     {
        0% { -ms-transform: rotate(0); }
        100% { -ms-transform: rotate(1800deg); }
     }</pre><pre class="css" style="font-size: 10px;"> #container
     {
        position:relative;
        width:100%;
        height:600px;
        overflow:hidden;        /*这个很重要*/
     }
    
     #car
     {
        position:absolute;      /*汽车在容器中采用绝对定位*/
        width:400px;
        height:210px;       /*汽车的总高度,包括轮胎和底盘*/
        z-index:1;          /*让汽车在背景的上方*/
        top:300px;          /*距顶端的距离(y轴)*/
        left:50px;          /*距左侧的距离(x轴)*/
    
        /*以下内容赋予该元素预先定义的动画及相关属性*/
        -webkit-animation-name:carAnimation;        /*名称*/
        -webkit-animation-duration:10s;         /*持续时间*/
        -webkit-animation-iteration-count:infinite;     /*迭代次数-无限次*/
        -webkit-animation-timing-function:linear;       /*播放动画时从头到尾都以相同的速度*/
    
        -moz-animation-name:carAnimation;       /*名称*/
        -moz-animation-duration:10s;            /*持续时间*/
        -moz-animation-iteration-count:infinite;        /*迭代次数-无限次*/
        -moz-animation-timing-function:linear;      /*播放动画时从头到尾都以相同的速度*/
    
        -ms-animation-name:carAnimation;        /*名称*/
        -ms-animation-duration:10s;         /*持续时间*/
        -ms-animation-iteration-count:infinite;     /*迭代次数-无限次*/
        -ms-animation-timing-function:linear;       /*播放动画时从头到尾都以相同的速度*/
    
        animation-name:carAnimation;        /*名称*/
        animation-duration:10s;         /*持续时间*/
        animation-iteration-count:infinite;     /*迭代次数-无限次*/
        animation-timing-function:linear;       /*播放动画时从头到尾都以相同的速度*/
     }
    
     /*车身*/
     #chassis
     {
        position:absolute;
        width:400px;
        height:130px;
        background:#FF9900;
        border: 2px solid #FF6600;
     }
    
     /*轮胎*/
     .tire
     {
        z-index:1;          /*同上,轮胎也应置于背景的上方*/
        position:absolute;
        bottom:0;
        border-radius:60px;     /*圆半径*/
        height:120px;       /* 2*radius=height */
        width:120px;        /* 2*radius=width */
        background:#0099FF;     /*填充色*/
        border:1px solid #3300FF;
    
        -webkit-animation-name:tyreAnimation;
        -webkit-animation-duration:10s;
        -webkit-animation-iteration-count:infinite;
        -webkit-animation-timing-function:linear;
    
        -moz-animation-name:tyreAnimation;
        -moz-animation-duration:10s;
        -moz-animation-iteration-count:infinite;
        -moz-animation-timing-function:linear;
    
        -ms-animation-name:tyreAnimation;
        -ms-animation-duration:10s;
        -ms-animation-iteration-count:infinite;
        -ms-animation-timing-function:linear;       
    
        animation-name:tyreAnimation;
        animation-duration:10s;
        animation-iteration-count:infinite;
        animation-timing-function:linear;
     }
    
     #fronttire
     {
        right:20px;     /*设置右边的轮胎距离边缘的距离为20*/
     }
    
     #backtire
     {
        left:20px;      /*设置左边的轮胎距离边缘的距离为20*/
     }
    
     #grass
     {
        position:absolute;  /*背景绝对定位在容器中*/
        width:100%;
        height:130px;
        bottom:0;
        /*让背景色线性渐变,bottom,表示渐变的起始处,第一个颜色值是渐变的起始值,第二个颜色值是终止值 */
        background:linear-grdaient(bottom,#33CC00,#66FF22);
        background:-webkit-linear-gradient(bottom,#33CC00,#66FF22);
        background:-moz-linear-gradient(bottom,#33CC00,#66FF22);
        background:-ms-linear-gradient(bottom,#33CC00,#66FF22); 
     }
    
     .hr,.vr
     {
        position:absolute;
        background:#3300FF;
     }
    
     .hr
     {
        height:1px;
        width:100%;     /*轮胎的水平线*/
        left:0;
        top:60px;
     }
    
     .vr
     {
        width:1px;
        height:100%;    /*轮胎的垂直线*/
        left:60px;
        top:0;
     }</pre><h3 id="t3"><a name="t3"></a><span style="font-size: 18px;">3.JQuery与CSS3</span></h3><p><span style="font-size: 10px;">这是一个效果与兼容性俱佳的方式(特别对于IE9暂不支持CSS3而言)</span></p><p><span style="font-size: 10px;">HTML代码(可以看到与CSS3中的HTML代码并无不同):</span></p><pre class="html">&lt;html&gt;
    

    <head>
    <meta charset=”UTF-8” />
    <title>Animations in HTML5 using CSS3 animations</title>
    </head>
    <body>
    <div id=”container”>
    <div id=”car”>
    <div id=”chassis”></div>
    <div id=”backtire” class=”tire”>
    <div class=”hr”></div>
    <div class=”vr”></div>
    </div>
    <div id=”fronttire” class=”tire”>
    <div class=”hr”></div>
    <div class=”vr”></div>
    </div>
    </div>
    <div id=”grass”></div>
    </div>
    <footer></footer>
    </body>
    </html>

    CSS:

    <style> 
    body
    {
    padding:0;
    margin:0;
    }
      #container
     {
        position:relative;
        width:100%;
        height:600px;
        overflow:hidden;        /*这个很重要*/
     }
    
     #car
     {
        position:absolute;      /*汽车在容器中采用绝对定位*/
        width:400px;
        height:210px;       /*汽车的总高度,包括轮胎和底盘*/
        z-index:1;          /*让汽车在背景的上方*/
        top:300px;          /*距顶端的距离(y轴)*/
        left:50px;          /*距左侧的距离(x轴)*/
     }
    
      /*车身*/
     #chassis
     {
        position:absolute;
        width:400px;
        height:130px;
        background:#FF9900;
        border: 2px solid #FF6600;
     }
    
     /*轮胎*/
     .tire
     {
        z-index:1;          /*同上,轮胎也应置于背景的上方*/
        position:absolute;
        bottom:0;
        border-radius:60px;     /*圆半径*/
        height:120px;       /* 2*radius=height */
        width:120px;        /* 2*radius=width */
        background:#0099FF;     /*填充色*/
        border:1px solid #3300FF;
        -o-transform:rotate(0deg);  /*旋转(单位:度)*/
        -ms-transform:rotate(0deg);
        -webkit-transform:rotate(0deg);
        -moz-transform:rotate(0deg);
     }
    
     #fronttire
     {
        right:20px;     /*设置右边的轮胎距离边缘的距离为20*/
     }
    
     #backtire
     {
        left:20px;      /*设置左边的轮胎距离边缘的距离为20*/
     }
    
     #grass
     {
        position:absolute;  /*背景绝对定位在容器中*/
        width:100%;
        height:130px;
        bottom:0;
        /*让背景色线性渐变,bottom,表示渐变的起始处,第一个颜色值是渐变的起始值,第二个颜色值是终止值 */
        background:linear-grdaient(bottom,#33CC00,#66FF22);
        background:-webkit-linear-gradient(bottom,#33CC00,#66FF22);
        background:-moz-linear-gradient(bottom,#33CC00,#66FF22);
        background:-ms-linear-gradient(bottom,#33CC00,#66FF22); 
     }
    
     .hr,.vr
     {
        position:absolute;
        background:#3300FF;
     }
    
     .hr
     {
        height:1px;
        width:100%;     /*水平线*/
        left:0;
        top:60px;
     }
    
     .vr
     {
        width:1px;
        height:100%;    /*垂直线*/
        left:60px;
        top:0;
     }
    
      &lt;/style&gt;</pre><p>JS代码:</p><p><span style="font-size: 10px;">首先引入在线API:</span></p><pre class="javascript">&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"&gt;&lt;/script&gt;</pre><p>实现动画代码(相当简洁):</p><pre class="javascript">&lt;script&gt;
         $(function(){
         var rot=0;
         var prefix=$('.tire').css('-o-transform')?'-o-transform':($('.tire').css('-ms-transform')?'-ms-transform':($('.tire').css('-moz-transform')?'-moz-transform':($('.tire').css('-webkit-transform')?'-webkit-transform':'transform')));
    
         var origin={       /*设置我们的起始点*/
         left:-400
         };
    
         var animation={        /*该动画由jQuery执行*/
         left:1600      /*设置我们将移动到的最终位置*/
     };
    
         var rotate=function(){ /*该方法将被旋转的轮子调用*/
         rot+=2;
         $('.tire').css(prefix,'rotate('+rot+'deg)');
     };
    
         var options={      /*将要被jQuery使用的参数*/
         easing:'linear',   /*指定速度,此处只是线性,即为匀速*/
         duration:10000,    /*指定动画持续时间*/
         complete:function(){
            $('#car').css(origin).animate(animation,options);
         },
         step:rotate
     };
    
         options.complete();
      });
      &lt;/script&gt;</pre><p>简单讲解:prefix首先识别出当前是哪个定义被采用了(-o?-moz?-webkit?-ms?),然后定义了动画的起点位置和终点位置。接着,定义了设置旋转角度的函数(该函数将在在动画的每一步(step)中执行)。然后,定义了一个动画,该定义方式导致了无限自循环调用!</p><p>本文,通过一个简单的动画实例,演示了<span class="wp_keywordlink_affiliate"><a href="http://caibaojian.com/t/html5" title="View all posts in HTML5" target="_blank">HTML5</a></span>下,实现动画的几种常见方式。</p><p>原文:http://blog.csdn.net/yanghua_kobe/article/details/7226816</p><div class="yarpp-related"><h3 class="widget-title">推荐文章</h3><ul><li><a href="http://caibaojian.com/css3-round.html" rel="bookmark">CSS3制作圆环进度动画效果</a></li><li><a href="http://caibaojian.com/css3-radial-progress-bar.html" rel="bookmark">纯CSS3实现圆弧(圆圈)百分比动画进度条</a></li><li><a href="http://caibaojian.com/jquery-circular-progress.html" rel="bookmark">jquery圆环百分比进度条制作</a></li><li><a href="http://caibaojian.com/css3-animate-spin.html" rel="bookmark">CSS揭秘之沿着环形路径运动的动画</a></li><li><a href="http://caibaojian.com/pure-css-icons.html" rel="bookmark">神奇的纯CSS图标</a></li></ul></div></div><div class="entry-details" itemprop="copyrightHolder" itemtype="http://schema.org/Organization" itemscope=""> 原创文章:<a href="http://caibaojian.com/3-html5-animations.html" rel="bookmark">HTML5实现动画三种方式</a> ,未经许可,禁止转载,<a target="_blank" href="http://caibaojian.com/copyright">©版权所有</a>。<br> 原文出处:前端开发博客 (<a href="http://caibaojian.com/3-html5-animations.html" title="HTML5实现动画三种方式">http://caibaojian.com/3-html5-animations.html</a>)</div><div class="da_container"> <img class="inner-box" src="http://caibaojian.com/a/a3.png"></div></div><div class="entry-footer clearfix" role="toolbar"><div class="bd-share"><div class="bdsharebuttonbox bdshare-button-style1-24" data-bd-bind="1504845402208"><a class="bds_qzone" data-cmd="qzone" title="分享到QQ空间"></a><a class="bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a><a class="bds_weixin" data-cmd="weixin" title="分享到微信"></a><a class="bds_more" data-cmd="more"></a></div><script>var share_excerpt = '【HTML5实现动画三种方式】编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是canvas,还有css3和javascript.通过合理的选择,来实现最优的实现。P... @前端开发博客';var share_pic = '';var share_url = 'http://caibaojian.com/3-html5-animations.html';var wkey = '3586943907';var qkey = '101187318';window._bd_share_main = false;window._bd_share_config = { common : { bdText : share_excerpt,bdDesc : share_excerpt,bdUrl : share_url, bdPic : share_pic, bdSnsKey : {'tsina':wkey, 'tqq':qkey,'qzone':qkey} }, share : [{ 'bdStyle' : 1, 'bdSize' : 24 }] };</script></div><div class="btn-group vote-group" data-votes-up="6" data-votes-down="0" data-vote-id="5039" data-vote-type="post" itemscope="" itemtype="http://data-vocabulary.org/Review-aggregate"> <span href="javascript:void(0)" class="btn btn-zs show-zs">¥ 打赏</span> <a href="javascript:;" class="btn btn-default up"><span class="glyphicon glyphicon-thumbs-up"></span> 赞(<span class="votes">6</span>)<div class="hide" itemprop="rating" itemscope="" itemtype="http://data-vocabulary.org/Rating"><span itemprop="average">5</span><span itemprop="votes">6</span><span itemprop="count">0</span></div></a> <a href="javascript:;" class="btn btn-default down"><span class="glyphicon glyphicon-thumbs-down"></span></a></div></div><div class="content-box-inner" id="weiboshow" itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization"> <script>window.onload = function(){
                    //document.getElementById("weiboshow").innerHTML = '<iframe width="100%" height="200" class="share_self"  frameborder="0" scrolling="no" src="http://widget.weibo.com/weiboshow/index.php?language=&width=0&height=220&fansRow=2&ptype=1&speed=0&skin=1&isTitle=0&noborder=1&isWeibo=0&isFans=1&uid=1748018491&verifier=5089da68&dpc=1"></iframe>';
                    }</script> </div><div class="relatedposts"><h3>相关文章</h3><ul class="related_posts inline-ul"><li class=""> <a rel="bookmark" href="http://caibaojian.com/canvas-circular.html" title="canvas绘制旋转的圆环百分比进度条">canvas绘制旋转的圆环百分比进度条</a><span class="entry-meta"> 9,432Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/modernizr-js.html" title="Modernizr.js:为HTML5和CSS3而生!">Modernizr.js:为HTML5和CSS3而生!</a><span class="entry-meta"> 24,990Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/the-best-webfrontend.html" title="为什么整个互联网行业都缺前端工程师?">为什么整个互联网行业都缺前端工程师?</a><span class="entry-meta"> 4,923Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/learn-jquery-plugin-tutorial.html" title="开始学习并将深入学习jQuery插件制作">开始学习并将深入学习jQuery插件制作</a><span class="entry-meta"> 1,716Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/js-lazyload.html" title="jQuery图片懒加载代码">jQuery图片懒加载代码</a><span class="entry-meta"> 1,681Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/css-equal-layout.html" title="CSS自适应布局等分比例实践">CSS自适应布局等分比例实践</a><span class="entry-meta"> 18,638Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/towards-retina-web.html" title="【译】走向Retina Web">【译】走向Retina Web</a><span class="entry-meta"> 1,417Views</span></li><li class=""> <a rel="bookmark" href="http://caibaojian.com/jquery-drag.html" title="jquery拖动代码">jquery拖动代码</a><span class="entry-meta"> 1,627Views</span></li></ul></div></article>
    

    原文:http://blog.csdn.net/yanghua_kobe/article/details/7226816

    展开全文
  • HTML5特效动画

    千次阅读 热门讨论 2019-05-21 17:37:31
    HTML5 Canvas 鼠标滑过3D动画背景 在网页中我们经常会设置元素的背景,简单点的设置背景颜色,复杂的就设置背景图片。今天给大家分享一个将HTML5canvas动画作为网页背景的例子,将canvas置于文本底部,canvas上绘制...

    7、

    HTML5 Canvas 鼠标滑过3D动画背景

    在网页中我们经常会设置元素的背景,简单点的设置背景颜色,复杂的就设置背景图片。今天给大家分享一个将HTML5 canvas动画作为网页背景的例子,将canvas置于文本底部,canvas上绘制很多3D图形,当我们将鼠标滑过背景时,canvas上的这些3D图形将会翻转,效果很酷。

    html5-canvas-3d-background

    在线演示源码下载

     

    6、

    基于Three.js的碰撞检测穿马路动画

     

    Three.js是JavaScript编写的WebGL第三方库,提供了非常多的3D显示功能。今天要给大家分享的就是一款基于Three.js的穿马路游戏动画,主要使用了Three.js的碰撞检测功能,马路上穿梭着很多车辆,你可以通过方向键控制小方块的行进方向,顺利通过马路,如果方块和行驶的车辆发生碰撞,则游戏结束。

    threejs-impact-checking

    在线演示源码下载

     

    5、

    纯CSS3超逼真的风车旋转动画

     

    很早以前,我们给大家分享过一款基于HTML5和CSS3的风车动画,效果还是不错的。这次我们介绍的同样是一个基于CSS3的风车旋转动画,只不过这个风车的元素更丰富,更像是在一个美丽的村庄中,一个风车在日落的渲染下不停的旋转工作。

    pure-css3-windmill

    在线演示源码下载

     

    4、

    HTML5 Canvas火焰跟随鼠标动画

     

    今天给大家分享一个效果很棒的HTML5 Canvas动画,它是一个火焰动画,这与我们之前分享的HTML Canvas火焰画笔动画类似,也是在Canvas上通过鼠标绘制而成。这个火焰动画会不停地跟随鼠标移动,如果你有一个游戏方面的宣传网页,那么这个动画可以用在鼠标移动上,应该是比较酷的。

    html5-canvas-fire-mouse

    在线演示源码下载

     

    3、

    CSS3根据渐变序列猜颜色游戏

     

    今天给大家分享一个基于CSS3和JavaScript的颜色辨析游戏,已知3个一组的方块,前面2个方块涂有相近的两种颜色,你根据这两种颜色序列的递减情况,猜测第三个方块的颜色是什么,并从下面的方块中选择你认为最接近的颜色,一起来测试一下自己的辨色能力吧。

    css3-guess-color

    在线演示源码下载

     

    2、HTML5 Emoji自定义表情编辑器

     

    Emoji表情在网页中使用十分广泛,它由一些简单的字符组成许多表情,例如笑脸、蛋糕等。今天我们要介绍一个基于HTML5和CSS3的Emoji自定义表情编辑器,初始默认是一个人脸,你可以在编辑器中为该人脸表情添加和改变各种面部表情,例如带上帽子,噘嘴等,甚至可以将其他任意Emoji表情添加上去,用起来非常不错。但是如果可以将编辑好的表情导出就更加完美了。

    html5-emoji-editor

    在线演示源码下载

     

    1、HTML5 Canvas烟花绽放庆祝活动场景

     

    前段时间,我们分享过几个基于HTML5 Canvas的烟花动画,例如这个2D平面的烟花动画,也是基于HTML5 Canvas的;同样的另外一个基于3D带音效的烟花燃放动画效果也非常炫酷。这次我们分享的另外一款基于HTML5 Canvas的烟花绽放动画的特点是,除了可以播放烟花动画,而且还可以用粒子动画的方式显示文本,例如公司名字,这样更是渲染了庆祝的氛围。

    html5-canvas-fireworks-celebrate

    在线演示源码下载

    展开全文
  • 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(frame-by-frame animation)和补间动画(tweened animation)。逐帧动画的工作原理很...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355


    在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(frame-by-frame animation)和补间动画(tweened animation)。逐帧动画的工作原理很简单,其实就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理。补间动画则是可以对View进行一系列的动画操作,包括淡入淡出、缩放、平移、旋转四种。


    然而自Android 3.0版本开始,系统给我们提供了一种全新的动画模式,属性动画(property animation),它的功能非常强大,弥补了之前补间动画的一些缺陷,几乎是可以完全替代掉补间动画了。对于逐帧动画和补间动画的用法,我不想再多讲,它们的技术已经比较老了,而且网上资料也非常多,那么今天我们这篇文章的主题就是对Android属性动画进行一次完全解析。


    为什么要引入属性动画?


    Android之前的补间动画机制其实还算是比较健全的,在android.view.animation包下面有好多的类可以供我们操作,来完成一系列的动画效果,比如说对View进行移动、缩放、旋转和淡入淡出,并且我们还可以借助AnimationSet来将这些动画效果组合起来使用,除此之外还可以通过配置Interpolator来控制动画的播放速度等等等等。那么这里大家可能要产生疑问了,既然之前的动画机制已经这么健全了,为什么还要引入属性动画呢?


    其实上面所谓的健全都是相对的,如果你的需求中只需要对View进行移动、缩放、旋转和淡入淡出操作,那么补间动画确实已经足够健全了。但是很显然,这些功能是不足以覆盖所有的场景的,一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操作,那么补间动画就不能再帮我们忙了,也就是说它在功能和可扩展方面都有相当大的局限性,那么下面我们就来看看补间动画所不能胜任的场景。


    注意上面我在介绍补间动画的时候都有使用“对View进行操作”这样的描述,没错,补间动画是只能够作用在View上的。也就是说,我们可以对一个Button、TextView、甚至是LinearLayout、或者其它任何继承自View的组件进行动画操作,但是如果我们想要对一个非View的对象进行动画操作,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会需要对一个非View的对象进行动画操作呢?这里我举一个简单的例子,比如说我们有一个自定义的View,在这个View当中有一个Point对象用于管理坐标,然后在onDraw()方法当中就是根据这个Point对象的坐标值来进行绘制的。也就是说,如果我们可以对Point对象进行动画操作,那么整个自定义View的动画效果就有了。显然,补间动画是不具备这个功能的,这是它的第一个缺陷。


    然后补间动画还有一个缺陷,就是它只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,那如果我们希望可以对View的背景色进行动态地改变呢?很遗憾,我们只能靠自己去实现了。说白了,之前的补间动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。


    最后,补间动画还有一个致命的缺陷,就是它只是改变了View的显示效果而已,而不会真正去改变View的属性。什么意思呢?比如说,现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。


    也正是因为这些原因,Android开发团队决定在3.0版本当中引入属性动画这个功能,那么属性动画是不是就把上述的问题全部解决掉了?下面我们就来一起看一看。


    新引入的属性动画机制已经不再是针对于View来设计的了,也不限定于只能实现移动、缩放、旋转和淡入淡出这几种动画操作,同时也不再只是一种视觉上的动画效果了。它实际上是一种不断地对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性。所以我们仍然可以将一个View进行移动或者缩放,但同时也可以对自定义View中的Point对象进行动画操作了。我们只需要告诉系统动画的运行时长,需要执行哪种类型的动画,以及动画的初始值和结束值,剩下的工作就可以全部交给系统去完成了。


    既然属性动画的实现机制是通过对目标对象进行赋值并修改其属性来实现的,那么之前所说的按钮显示的问题也就不复存在了,如果我们通过属性动画来移动一个按钮,那么这个按钮就是真正的移动了,而不再是仅仅在另外一个位置绘制了而已。


    好了,介绍了这么多,相信大家已经对属性动画有了一个最基本的认识了,下面我们就来开始学习一下属性动画的用法。


    ValueAnimator


    ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。


    但是ValueAnimator的用法却一点都不复杂,我们先从最简单的功能看起吧,比如说想要将一个值从0平滑过渡到1,时长300毫秒,就可以这样写:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    anim.setDuration(300);
    anim.start();

    怎么样?很简单吧,调用ValueAnimator的ofFloat()方法就可以构建出一个ValueAnimator的实例,ofFloat()方法当中允许传入多个float类型的参数,这里传入0和1就表示将值从0平滑过渡到1,然后调用ValueAnimator的setDuration()方法来设置动画运行的时长,最后调用start()方法启动动画。


    用法就是这么简单,现在如果你运行一下上面的代码,动画就会执行了。可是这只是一个将值从0过渡到1的动画,又看不到任何界面效果,我们怎样才能知道这个动画是不是已经真正运行了呢?这就需要借助监听器来实现了,如下所示:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    anim.setDuration(300);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float currentValue = (float) animation.getAnimatedValue();
            Log.d("TAG", "cuurent value is " + currentValue);
        }
    });
    anim.start();

    可以看到,这里我们通过addUpdateListener()方法来添加一个动画的监听器,在动画执行的过程中会不断地进行回调,我们只需要在回调方法当中将当前的值取出并打印出来,就可以知道动画有没有真正运行了。运行上述代码,控制台打印如下所示:




    从打印日志的值我们就可以看出,ValueAnimator确实已经在正常工作了,值在300毫秒的时间内从0平滑过渡到了1,而这个计算工作就是由ValueAnimator帮助我们完成的。另外ofFloat()方法当中是可以传入任意多个参数的,因此我们还可以构建出更加复杂的动画逻辑,比如说将一个值在5秒内从0过渡到5,再过渡到3,再过渡到10,就可以这样写:

    ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);
    anim.setDuration(5000);
    anim.start();
    当然也许你并不需要小数位数的动画过渡,可能你只是希望将一个整数值从0平滑地过渡到100,那么也很简单,只需要调用ValueAnimator的ofInt()方法就可以了,如下所示:
    ValueAnimator anim = ValueAnimator.ofInt(0, 100);

    ValueAnimator当中最常用的应该就是ofFloat()和ofInt()这两个方法了,另外还有一个ofObject()方法,我会在下篇文章进行讲解。


    那么除此之外,我们还可以调用setStartDelay()方法来设置动画延迟播放的时间,调用setRepeatCount()和setRepeatMode()方法来设置动画循环播放的次数以及循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放的意思。这些方法都很简单,我就不再进行详细讲解了。


    ObjectAnimator


    相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。


    不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似,这里如果我们想要将一个TextView在5秒中内从常规变换成全透明,再从全透明变换成常规,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
    animator.setDuration(5000);
    animator.start();

    可以看到,我们还是调用了ofFloat()方法来去创建一个ObjectAnimator的实例,只不过ofFloat()方法当中接收的参数有点变化了。这里第一个参数要求传入一个object对象,我们想要对哪个对象进行动画操作就传入什么,这里我传入了一个textview。第二个参数是想要对该对象的哪个属性进行动画操作,由于我们想要改变TextView的不透明度,因此这里传入"alpha"。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值,这里传入的值就表示将TextView从常规变换成全透明,再从全透明变换成常规。之后调用setDuration()方法来设置动画的时长,然后调用start()方法启动动画,效果如下图所示:




    学会了这一个用法之后,其它的用法我们就可以举一反三了,那比如说我们想要将TextView进行一次360度的旋转,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
    animator.setDuration(5000);
    animator.start();

    可以看到,这里我们将第二个参数改成了"rotation",然后将动画的初始值和结束值分别设置成0和360,现在运行一下代码,效果如下图所示:




    那么如果想要将TextView先向左移出屏幕,然后再移动回来,就可以这样写:

    float curTranslationX = textview.getTranslationX();
    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
    animator.setDuration(5000);
    animator.start();

    这里我们先是调用了TextView的getTranslationX()方法来获取到当前TextView的translationX的位置,然后ofFloat()方法的第二个参数传入"translationX",紧接着后面三个参数用于告诉系统TextView应该怎么移动,现在运行一下代码,效果如下图所示:




    然后我们还可以TextView进行缩放操作,比如说将TextView在垂直方向上放大3倍再还原,就可以这样写:

    ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
    animator.setDuration(5000);
    animator.start();

    这里将ofFloat()方法的第二个参数改成了"scaleY",表示在垂直方向上进行缩放,现在重新运行一下程序,效果如下图所示:




    到目前为止,ObjectAnimator的用法还算是相当简单吧,但是我相信肯定会有不少朋友现在心里都有同样一个疑问,就是ofFloat()方法的第二个参数到底可以传哪些值呢?目前我们使用过了alpha、rotation、translationX和scaleY这几个值,分别可以完成淡入淡出、旋转、水平移动、垂直缩放这几种动画,那么还有哪些值是可以使用的呢?其实这个问题的答案非常玄乎,就是我们可以传入任意的值到ofFloat()方法的第二个参数当中。任意的值?相信这很出乎大家的意料吧,但事实就是如此。因为ObjectAnimator在设计的时候就没有针对于View来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。


    那么比如说我们调用下面这样一段代码:

    ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);

    其实这段代码的意思就是ObjectAnimator会帮我们不断地改变textview对象中alpha属性的值,从1f变化到0f。然后textview对象需要根据alpha属性值的改变来不断刷新界面的显示,从而让用户可以看出淡入淡出的动画效果。


    那么textview对象中是不是有alpha属性这个值呢?没有,不仅textview没有这个属性,连它所有的父类也是没有这个属性的!这就奇怪了,textview当中并没有alpha这个属性,ObjectAnimator是如何进行操作的呢?其实ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法,因此alpha属性所对应的get和set方法应该就是:

    public void setAlpha(float value);
    public float getAlpha();

    那么textview对象中是否有这两个方法呢?确实有,并且这两个方法是由View对象提供的,也就是说不仅TextView可以使用这个属性来进行淡入淡出动画操作,任何继承自View的对象都可以的。


    既然alpha是这个样子,相信大家一定已经明白了,前面我们所用的所有属性都是这个工作原理,那么View当中一定也存在着setRotation()、getRotation()、setTranslationX()、getTranslationX()、setScaleY()、getScaleY()这些方法,不信的话你可以到View当中去找一下。


    组合动画


    独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。幸运的是,Android团队在设计属性动画的时候也充分考虑到了组合动画的功能,因此提供了一套非常丰富的API来让我们将多个动画组合到一起。


    实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

    • after(Animator anim)   将现有动画插入到传入的动画之后执行
    • after(long delay)   将现有动画延迟指定毫秒后执行
    • before(Animator anim)   将现有动画插入到传入的动画之前执行
    • with(Animator anim)   将现有动画和传入的动画同时执行

    好的,有了这四个方法,我们就可以完成组合动画的逻辑了,那么比如说我们想要让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
    ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
    ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
    AnimatorSet animSet = new AnimatorSet();
    animSet.play(rotate).with(fadeInOut).after(moveIn);
    animSet.setDuration(5000);
    animSet.start();

    可以看到,这里我们先是把三个动画的对象全部创建出来,然后new出一个AnimatorSet对象之后将这三个动画对象进行播放排序,让旋转和淡入淡出动画同时进行,并把它们插入到了平移动画的后面,最后是设置动画时长以及启动动画。运行一下上述代码,效果如下图所示:




    Animator监听器


    在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。


    大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。


    添加一个监听器的代码如下所示:

    anim.addListener(new AnimatorListener() {
    	@Override
    	public void onAnimationStart(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationRepeat(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationEnd(Animator animation) {
    	}
    
    	@Override
    	public void onAnimationCancel(Animator animation) {
    	}
    });

    可以看到,我们需要实现接口中的四个方法,onAnimationStart()方法会在动画开始的时候调用,onAnimationRepeat()方法会在动画重复执行的时候调用,onAnimationEnd()方法会在动画结束的时候调用,onAnimationCancel()方法会在动画被取消的时候调用。


    但是也许很多时候我们并不想要监听那么多个事件,可能我只想要监听动画结束这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。没关系,为此Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:

    anim.addListener(new AnimatorListenerAdapter() {
    });
    这里我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,如下所示:
    anim.addListener(new AnimatorListenerAdapter() {
    	@Override
    	public void onAnimationEnd(Animator animation) {
    	}
    });


    使用XML编写动画


    我们可以使用代码来编写所有的动画功能,这也是最常用的一种做法。不过,过去的补间动画除了使用代码编写之外也是可以使用XML编写的,因此属性动画也提供了这一功能,即通过XML来完成和代码一样的属性动画功能。


    通过XML来编写动画可能会比通过代码来编写动画要慢一些,但是在重用方面将会变得非常轻松,比如某个将通用的动画编写到XML里面,我们就可以在各个界面当中轻松去重用它。


    如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:

    • <animator>  对应代码中的ValueAnimator
    • <objectAnimator>  对应代码中的ObjectAnimator
    • <set>  对应代码中的AnimatorSet

    那么比如说我们想要实现一个从0到100平滑过渡的动画,在XML当中就可以这样写:

    <animator xmlns:android="http://schemas.android.com/apk/res/android"
        android:valueFrom="0"
        android:valueTo="100"
        android:valueType="intType"/>
    而如果我们想将一个视图的alpha属性从1变成0,就可以这样写:
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:valueFrom="1"
        android:valueTo="0"
        android:valueType="floatType"
        android:propertyName="alpha"/>
    其实XML编写动画在可读性方面还是挺高的,上面的内容相信不用我做解释大家也都看得懂吧。


    另外,我们也可以使用XML来完成复杂的组合动画操作,比如将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:

    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering="sequentially" >
    
        <objectAnimator
            android:duration="2000"
            android:propertyName="translationX"
            android:valueFrom="-500"
            android:valueTo="0"
            android:valueType="floatType" >
        </objectAnimator>
    
        <set android:ordering="together" >
            <objectAnimator
                android:duration="3000"
                android:propertyName="rotation"
                android:valueFrom="0"
                android:valueTo="360"
                android:valueType="floatType" >
            </objectAnimator>
    
            <set android:ordering="sequentially" >
                <objectAnimator
                    android:duration="1500"
                    android:propertyName="alpha"
                    android:valueFrom="1"
                    android:valueTo="0"
                    android:valueType="floatType" >
                </objectAnimator>
                <objectAnimator
                    android:duration="1500"
                    android:propertyName="alpha"
                    android:valueFrom="0"
                    android:valueTo="1"
                    android:valueType="floatType" >
                </objectAnimator>
            </set>
        </set>
    
    </set>
    这段XML实现的效果和我们刚才通过代码来实现的组合动画的效果是一模一样的,每个参数的含义都非常清楚,相信大家都是一看就懂,我就不再一一解释了。


    最后XML文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?只需调用如下代码即可:

    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
    animator.setTarget(view);
    animator.start();
    调用AnimatorInflater的loadAnimator来将XML动画文件加载进来,然后再调用setTarget()方法将这个动画设置到某一个对象上面,最后再调用start()方法启动动画就可以了,就是这么简单。


    好的,通过本篇文章的学习,我相信大家已经对属性动画的基本用法已经有了一个相当不错的认识,并把最常用的一些功能都掌握好了,那么本篇文章的内容就到这里,下篇文章当中会继续介绍属性动画,讲解ValueAnimator和ObjectAnimator的高级用法,感兴趣的朋友请继续阅读 Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法 。


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 经典flash动画短片

    千次下载 热门讨论 2020-07-27 23:33:53
    聊斋志异flash制作经典动画短片,初学者可以借鉴学习,交作业的话应该是相当不错的flash作业!很有创意也很有诗意!相信不会白下载!
  • 关于WPF动画

    千次阅读 2019-06-10 08:36:38
    在编写WPF中我们的样式都是静态的,于是WPF给我们提供了动画,让我们的窗口,页面或是控件“动了”。 在动画中,可以使用移动的元素、颜色变化、变换等制作平滑的变换效果。WPF是动画的制作非常简单。还可以连续...
  • 小程序学习:动画animation

    万次阅读 2019-07-11 15:47:38
    wxml: <view class="box"> <view class="headerimg" bindtap="click" animation="{{animationData}}"> <open-data type="userAvatarUrl" ></open-data> &l...
  • 动画 animation

    2019-11-06 16:38:32
    制作动画分为两步: 在css中定义动画函数 给目标元素调用动画函数 动画序列: 0% 是动画的开始,100% 是动画的完成。这样的规则就是动画序列。 在 @keyframes 中规定某项 CSS 样式,就能创建由当前样式逐渐改为新...
  • 1.动画过渡 将两个动画拖入Animator里面,设置两个Tigger条件。 选择一个转换 属性说明 Property Function Has Exit Time 可以退出时间   退出时间是一个不...
  • 今天给大家一个使用View Animation实现动画加载界面的实现。  首先先看一下实现效果。    下面是实现代码 [java] view plaincopy package com.example
  • 从本节开始我们来探究Android中的动画,毕竟在APP中添加上一些动画,会让我们的应用变得 很炫,比如最简单的关开Activity,当然自定义控件动画肯定必不可少啦~而Android中的动画 分为三大类,逐帧动画(Frame)以及...
  • 大家好,欢迎继续回到Android属性动画完全解析。在上一篇文章当中我们学习了属性动画的一些进阶技巧,包括ValueAnimator和ObjectAnimator的高级用法,那么除了这些之外,当然还有一些其它的高级技巧在等着我们学习,...
  • 动画:用动画给面试官解释 TCP 三次握手过程

    万次阅读 多人点赞 2020-04-11 22:50:08
    来源 | 公众号:小鹿动画学编程 写在前边 TCP 三次握手过程对于面试是必考的一个,所以不但要掌握 TCP 整个握手的过程,其中有些小细节也更受到面试官的青睐。 对于这部分掌握以及 TCP 的四次挥手,小鹿将会以...
  • 但是,正如上篇文章当中所说到的,属性动画对补间动画进行了很大幅度的改进,之前补间动画可以做到的属性动画也能做到,补间动画做不到的现在属性动画也可以做到了。因此,今天我们就来学习一下属性动画的高级用法,...
  • 本节给带来的是Android动画中的第三种动画——属性动画(Property Animation), 记得在上一节Android基础入门教程——8.4.2 Android动画合集之补间动画为Fragment 设置过渡动画的时候,说过,App包和V4包下的...
  • Android属性动画深入分析:让你成为动画牛人

    万次阅读 多人点赞 2014-01-05 23:41:02
    前言 感谢你阅读本文,我坚信读完本文肯定不会让你失望的。...关于动画,我已经写了两篇博文,但是还是没有将动画描述全面,于是我写了本文,另外,我后面还会再写一篇属性动画的源码分析,通过这四篇博文,
  • Android动画效果集合开源APP(BaseAnimation1.3)程序源码

    千次下载 热门讨论 2020-07-27 23:31:05
    BaseAnimation1.3版本增加如下动画 1.Splash增加2个动画 2.高仿动画效果增加10个 3.ListView集合增加15个 4.自定义控件集合增加17个 5.页面滑动增加4个 共增加48个动画效果 下载app源码的朋友需要把 BAnim ...
  • 用css3的animation完成一个动画,当只有这个动画完成时才执行令一个事件,比如让动画保持在终止的状态或其他一些事件。我们该怎么办呢。  第一种方法:  用计时器,设定一个和动画时长一样的time,过time事件去...
  • Android 属性动画(Property Animation) 完全解析 (上)

    万次阅读 多人点赞 2016-08-10 19:33:48
    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/380674751、概述Android提供了几种...View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且有一定的局限性。比如
  • Qt 之动画框架

    万次阅读 多人点赞 2018-05-30 10:15:25
    通过Qt动画属性,该框架为部件和其它QObject对象的动画操作提供了非常大的自由性,框架也可以被用于图形视图框架中,动画框架中许多可用的概念也可以用于Qt Quick,它提供了一种声明式的方式定义动画。大部分关于...
1 2 3 4 5 ... 20
收藏数 601,150
精华内容 240,460
关键字:

动画