前言

动画效果一直是人机交互的一个非常重要的部分,动画效果的引入,会让交互变得更加友好,让用户获得更加愉悦的体验。而随着市场环境变化,手机性能越来越好,网速越来越快,以及用户视觉效果要求越来越高,作为一名网页开发者,动画也是一个必会的技能。由此本文和大家分享下动画方面的技术实践经验。

动画的形成

多张不同的图像连在一起就会变成了动态的图像。在网页端的世界里,浏览器在视觉暂留时间内,连续不断的逐帧输出图像。每一帧输出一张图像,形成了用户视觉效果中的动画。那么怎么高效的通过一帧帧输出连续流畅的动画,是有很多种动画技术可以都可以实现的。

动画技术

下面以当今主流的动画技术,分成四个部分给大家介绍下,分别为纯CssLottie库Svga库Creatjs库

一、纯CSS

1.1 Animation动画属性主要结合@keyframes规则来创建动画。

下面以语音喇叭声波动效为例: 中间的小圆点是一直存在的,第一条和第二条线都是1/4的圆弧,分别间隔0.2s去循环显示隐藏。

声波动效.gif

.second {
    animation: fadeInOut 1s infinite 0.2s;
}
.third {
   animation: fadeInOut 1s infinite 0.4s;
}
@keyframes fadeInOut {
  0% {
    opacity: 0;
    /*初始状态 透明度为0*/
  }
  100% {
    opacity: 1;
    /*结尾状态 透明度为1*/
  }
}

我们一般用阶跃函数step来做帧动画。 下面是linearstep的具体案例:

https://codepen.io/huihui/pen/ExPKbdj

先生成Sprite图片,再移动X轴位置形成帧动画。

image1.png

linear-step.gif

1.2 Transform属性应用于元素的2D或3D转换。该属性允许我们对元素进行旋转、缩放、倾斜、移动、透视以及使用矩阵函数。分别为rotatescaleskewtranslateperspective以及matrix。还可以通过transform-origin用来确定中心点的位置为X、Y、Z,默认值:50% 50% 0。 这里有个很好的例子来演示Transform属性:https://c.runoob.com/codedemo/3391

transform.gif

下面以翻牌动效为例,主要是通过透视perspective属性来实现:

要达到图中第一组翻牌的效果。首先设置transform-style: preserve-3d,使被转换的子元素保留其3D转换。如果不加透视距离perspective,则会为第三组翻牌中的效果,扁平没有Z轴的立体感。其次添加了透视距离后,如果Z轴相同,三个卡片是会有重叠的现象,如第二组翻牌中的效果。最后特意给卡片一加大了Z轴距离。这样通过透视,如果Z轴距离越大,卡片就看上去越小。可以用scale放大了卡片一

排行榜翻牌.gif

.card-board{
  perspective: 800;
}
.board-item-wrap1{
  transform: scale(1.1) translateZ(-100px);
}

提示:一般用transform: translateZ(0),开启3D引擎,触发GPU加速,让网页动画更流畅。

1.3 Transition属性是用来设置动画过渡效果的,可以设置动画的过渡时间和延迟时间。还可以添加动画函数animation-timing-function,其默认值为ease。可用贝塞尔曲线来做为动画速度曲线,推荐一个贝塞尔曲线的可视化网址:cubic-bezier

贝塞尔曲线.gif 以地图页的动画为例: 品牌岛屿的移动效果用了ease,由于后面的品牌需要模糊,设置了较晚模糊的贝塞尔曲线

map.gif

transition: transform 1s ease,filter 1s cubic-bezier(.06,.45,.82,1.34);

https://cubic-bezier.com/#.06,.45,.82,1.34

image2.png

1.4 Js动画事件监听: 动画事件有:

animationstart - CSS动画开始后触发

animationiteration- CSS 动画重复播放时触发

animationend - CSS动画完成后触发

过渡事件有:

transitionend- 该事件在 CSS 完成过渡后触发。

注意:transitionend存在个问题.如果transition中,变换的属性有多个,就会触发多次。比如如果同时设置宽高的过渡效果(transition:width:.2s,height:.2s),那么transitionend事件就会触发2次。

2秒消失提示框为例:

动画结束2秒后隐藏,用animationEnd事件来监听。

toast.gif

兼容性: 上面4个事件都存在兼容性问题,在Android5下或Ios9.3下都需要加webkit前缀才能兼容,例如animationstart事件在Android5下需要用webkitAnimationStart

webkit.png

兼容性这块本人封装了插件jdyfe-eventployfill,原理是用createElement创建一个元素但是不插入页面Dom,查找style中是否有动画事件,来作为webkit的兼容判断 使用方法

import { janimationstart, janimationiteration, janimationend, jtransitionend } from'jdyfe-eventPloyfill'
    ...
    dom.addEventListener(janimationstart, ()=>{})
    dom.addEventListener(janimationiteration, ()=>{})
    dom.addEventListener(janimationend, ()=>{})
    dom.addEventListener(jtransitionend, ()=>{})
    ...

二、Lottie

airbnb提供的开源动画库Lottie

支持多版本,React NativewebiOSAndroid 版本

用矢量图导出。

在浏览器中生成的是svg标签,不会失真

案例为: https://codepen.io/airnan/pen/MPmQQB

var svgContainer = document.getElementById('svgContainer')
var animItem = bodymovin.loadAnimation({
  wrapper: svgContainer,//div的id
  animType: 'svg'
  loop: true,
  path: 'https://labs.nearpod.com/bodymovin/demo/markus/halloween/markus.json'
})

更多Lottie案例:https://codepen.io/collection/nVYWZR/

Lottie还和京东的JDReact框架结合,推出了JDLottieLoadingViewJDLottieView组件。其中JDLottieLoadingView主要是显示加载中的动效,会默认引用loading动画样式。JDLottieViewLottieJDReact上的封装,用法不变。

案例代码如下:

<JDLottieLoadingView
    autoSize={false} 
    source={"loading.json"}
/>
<JDLottieView
    autoPlay={true}
    autoSize={true}
    style=
    source={require('./animations/LottieWalkthrough')}
    progress={0}
    loop={true}
/>

三、Svga

SVGA 是一种跨平台的开源动画格式,集成 svga player 之后可直接使用,安装svgaplayerweb包即可,

支持多版本,兼容 iOS / Android / Flutter / Web 多个平台的动画格式

支持位图和矢量图

在浏览器中生成的是canvas标签

案例代码如下:

import * as SVGA from 'svgaplayerweb'
function AniSvga(props) {
  useEffect(() => {
    var player = new SVGA.Player('#demoCanvas1')
    var parser = new SVGA.Parser('#demoCanvas1') // Must Provide same selector eg:#demoCanvas IF support IE6+
    parser.load('./plugin/mengniu.svga', function(videoItem) {
        player.setVideoItem(videoItem)
        player.startAnimation()
    })
    return ()=>{
      player.clear()
    }
  }, [])
  return (
    <div className="jdyfe-svgaPage">
      <div id="demoCanvas1" ></div>
    </div>
  )
}
export default AniSvga

svga在线预览:https://svga.io/svga-preview.html

某些Android操作系统缺少Blob支持,所以需要自行添加Blob Polyfill

image3.png

<script src="//cdn.bootcss.com/blob-polyfill/1.0.20150320/Blob.min.js"></script>

四、Createjs

CreateJS是基于HTML5开发的一套模块化的工具库。 基于这些库,可以非常快捷地开发出基于HTML5的游戏、动画和交互应用。

4.1 EaselJS

EaselJS提供了JavaScript库,可轻松操作HTML5 Canvas元素。

可以绘制Stage舞台、Container容器和Sprite精灵的大小位置等,还提供很多事件可以做交互,很适合纯互动游戏制作。 精灵可以用TexturePacker 软件来生成雪碧图,导出Createjsjson文件。

image4.png

4.2 TweenJs

TweenJs主要是调整动画属性,例如

target.alpha = 1
createjs.Tween.get(target).wait(500).to({alpha:0, visible:false}, 1000).call(handleComplete)
function handleComplete() {
        //渐变完成执行
}

这个渐变将会先等待0.5秒,渐变目标的alpha属性从0到1,并且visible属性从true变为false,这个过程用时1秒,最后调用handleComplete函数。

4.3 SoundJs

SoundJs主要用来加载处理音频的。

暂停,恢复 声音

控制声音的音量,静音

监听声音实例中的事件,如完成,循环,或失败事件

 createjs.Sound.alternateExtensions = ["mp3"]
 createjs.Sound.on("fileload", this.loadHandler, this)
 createjs.Sound.registerSound("path/to/mySound.ogg", "sound")
 function loadHandler(event) {
     // 这会引发针对每个已注册的声音。
     var instance = createjs.Sound.play("sound")  // 发挥使用ID。也可以使用完整的源路径或event.src。
     instance.on("complete", this.handleComplete, this)
     instance.volume = 0.5
 }
4.4 PreloadJS

PreloadJS是一个用来管理和协调相关资源加载的类库,它可以帮助你预先加载相关资源。对比自己写监听load事件来确认完成加载,PreloadJS更方便,并且支持预加载多种类型的数据,例如:图片、文件、音频、数据等等。 PreloadJS主要是用URL. createObjectURL 创建了Blob对象,然后赋值给URL,移除的时候用 URL.revokeObjectURL方法移除Blob对象。所以会在network中看到Blob对象。

import createjs from 'jdyfe-createjs'
const loader = new createjs.LoadQueue(true)
loader.loadManifest([bgAry[0], ...imgAry])
loader.on('complete', function () {
       console.log('complete')//全部加载完成
})
loader.on('fileload', function (e) {
       console.log('fileload---', e.target.progress)//进度条
})

案例

createjs官网不支持npm方式使用,我们用webpack重新打包生成了一个umd模块jdyfe-createjs,可供大家下载和使用。

下面案例包含了上面说的4个模块,也用到了jdyfe-createjs,具体可看:Belly跑步案例

createjs.gif

Happy coding .. :)

相关链接

https://developer.mozilla.org/en-US/docs/Web/API/Animation/play

http://www.createjs.cc/src/docs/tweenjs/classes/CSSPlugin.html

Comments评论



也可直接在issue下评论 https://github.com/raoenhui/raoenhui.github.io/issues