如何实现小程序动画?小程序动画的实现方法
来源:小白
发布时间:2018-11-14 09:53:27
阅读量:1395
本篇文章给大家带来的内容是介绍如何实现小程序动画?小程序动画的实现方法。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。
在普通的网页开发中,动画效果可以通过css3来实现大部分需求,在小程序开发中同样可以使用css3
,同时也可以通过api
方式来实现。
API解读
小程序中,通过调用api
来创建动画,需要先创建一个实例对象。这个对象通过wx.createAnimation
返回,animation
的一系列属性都基于这个实例对象。
创建这个对象
1 2 3 4 5 | let animation = wx.createAnimation({
duration: 2000,
delay: 0,
timingFunction: "linear" ,
});
|
这个animation
就是通过wx.createAnimation
之后返回的实例。在创建过程中,可以给这个实例添加一些属性,如以上代码所示,等同于css3
中animation:$name 2s linear
的写法。
添加动效
实例创建完成之后,基于该实例,添加需要的动态效果,动态类型可以查阅文档得知,以最常见的移动,旋转为例:
1 | animation.translate( $width , 0).rotate( $deg );
|
结束动画
.step()
表示一组动画的结束
导出动画
动画效果添加完成了,如何给想要的dom添加动效呢。这里需要用到.export()
导出动画队列,赋值给某个dom对象。
1 | this.setData({ moveOne: animation.export() })
|
1 | <view animation= "{{moveOne}}" ></view>
|
例子
以下将通过2组动画,来对比一下css3
与api
实现方式的不同。
一、模块移动动画
动画效果:
下图有两组动画,分别为api
方式(上)与css3
方式(下)完成的效果,点击move按钮,动画启动。

代码实现
以下分别为css3
与api
的核心代码:
css3:
1 2 3 4 5 6 7 | <!-- wxml -->
<view class = 'border' >
<view class = 'css-block {{isMove && "one"}}' ></view>
<view class = 'css-block {{isMove && "two"}}' ></view>
<view class = 'css-block {{isMove && "three"}}' ></view>
<view class = 'css-block {{isMove && "four"}}' ></view>
</view>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | @mixin movePublic( $oldLeft , $oldTop , $left , $top ) {
from {
transform:translate( $oldLeft , $oldTop );
}
to {
transform:translate( $left , $top );
}
}
@mixin blockStyle( $color , $name ) {
background: $color ;
animation: $name 2s linear infinite alternate;
}
.one {
@ include blockStyle(lightsalmon,onemove);
}
@keyframes onemove {
@ include movePublic(50rpx,-25rpx,-150rpx,0rpx);
}
.two {
@ include blockStyle(lightblue,twomove);
}
@keyframes twomove {
@ include movePublic(0rpx,25rpx,-50rpx,0rpx);
}
.three {
@ include blockStyle(lightgray,threemove);
}
@keyframes threemove {
@ include movePublic(0rpx,25rpx,50rpx,0rpx);
}
.four {
@ include blockStyle(grey,fourmove);
}
@keyframes fourmove {
@ include movePublic(-50rpx,-25rpx,150rpx,0rpx);
}
|
1 2 3 4 5 6 | moveFunction(){
this.setData({
isMove: true
})
}
|
css3
中通过动态改变class
类名来达到动画的效果,如上代码通过one
、two
、three
、four
来分别控制移动的距离,通过sass可以避免代码过于冗余的问题。(纠结如何在小程序中使用sass
的童鞋请看这里哦:wechat-mina-template)
api:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | moveClick(){
this.move(-75,-12.5,25, 'moveOne' );
this.move(-25,12.5, 0, 'moveTwo' );
this.move(25, 12.5,0, 'moveThree' );
this.move(75, -12.5,-25, 'moveFour' );
this.moveFunction();
},
move: function (w,h,m,ele) {
let self = this;
let moveFunc = function () {
let animation = wx.createAnimation({
duration: 2000,
delay: 0,
timingFunction: "linear" ,
});
animation.translate(w, 0).step()
self.setData({ [ele]: animation.export() })
let timeout = setTimeout( function () {
animation.translate(m, h).step();
self.setData({
[ele]: animation.export()
})
}.bind(this), 2000)
}
moveFunc();
let interval = setInterval(moveFunc,4000)
}
|
效果图可见,模块之间都是简单的移动,可以将他们的运动变化写成一个公共的事件,通过向事件传值,来移动到不同的位置。其中的参数w,h,m,ele
分别表示发散水平方向移动的距离、聚拢时垂直方向、水平方向的距离以及需要修改animationData
的对象。
通过这种方法产生的动画,无法按照原有轨迹收回,所以在事件之后设置了定时器,定义在执行动画2s之后,执行另一个动画。同时动画只能执行一次,如果需要循环的动效,要在外层包裹一个重复执行的定时器到。
查看源码,发现api
方式是通过js
插入并改变内联样式来达到动画效果,下面这张动图可以清晰地看出样式变化。

打印出赋值的animationData
,animates
中存放了动画事件的类型及参数;options
中存放的是此次动画的配置选项,transition
中存放的是wx.createAnimation
调用时的配置,transformOrigin
是默认配置,意为以对象的中心为起点开始执行动画,也可在wx.createAnimation
时进行配置。

二、音乐播放动画
上面的模块移动动画不涉及逻辑交互,因此新尝试了一个音乐播放动画,该动画需要实现暂停、继续的效果。
动画效果:

两组不同的动画效果对比,分别为api
(上)实现与css3
实现(下):

代码实现
以下分别是css3
实现与api
实现的核心代码:
css3:
1 2 3 4 5 | <!-- wxml -->
<view class = 'music musicTwo musicRotate {{playTwo ? " ": "musicPaused"}} ' bindtap= 'playTwo' >
<text class = "iconfont has-music" wx: if = "{{playTwo}}" ></text>
<text class = "iconfont no-music" wx: if = "{{!playTwo}}" ></text>
</view>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | .musicRotate{
animation: rotate 3s linear infinite;
}
@keyframes rotate{
from{
transform: rotate(0deg)
}
to{
transform: rotate(359deg)
}
}
.musicPaused{
animation-play-state: paused;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | playTwo(){
this.setData({
playTwo: !this.data.playTwo
},()=>{
let back = this.data.backgroundAudioManager;
if (this.data.playTwo){
back.play();
} else {
back.pause();
}
})
}
|
通过playTwo
这个属性来判断是否暂停,并控制css
类的添加与删除。当为false
时,添加.musicPaused
类,动画暂停。
api:
1 2 3 4 5 | <!-- wxml -->
<view class = 'music' bindtap= 'play' animation= "{{play && musicRotate}}" >
<text class = "iconfont has-music" wx: if = "{{play}}" ></text>
<text class = "iconfont no-music" wx: if = "{{!play}}" ></text>
</view>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | play(){
this.setData({
play: !this.data.play
},()=>{
let back = this.data.backgroundAudioManager;
if (!this.data.play) {
back.pause();
clearInterval(this.data.rotateInterval);
} else {
back.play();
this.musicRotate(this.data.i);
}
})
},
musicRotate(i){
let self = this;
let rotateFuc = function (){
i++;
self.setData({
i:i++
});
let animation = wx.createAnimation({
duration: 1000,
delay: 0,
timingFunction: "linear" ,
});
animation.rotate(30*(i++)).step()
self.setData({ musicRotate: animation.export() });
}
rotateFuc();
let rotateInterval = setInterval(
rotateFuc,1000
);
this.setData({
rotateInterval: rotateInterval
})
}
|
通过api
实现的方式是通过移除animationData
来控制动画,同时暂停动画也需要清除定时器,由于清除定时器需要跨事件进行操作,所以定了一个全局方法rotateInterval
。
api
方式定义了旋转的角度,但旋转到该角度之后便会停止,如果需要实现重复旋转效果,需要通过定时器来完成。因此定义了变量i,定时器每执行一次便加1,相当于每1s旋转30°,对animation.rotate()
中的度数动态赋值。暂停之后继续动画,需要从原有角度继续旋转,因此变量i需要为全局变量。
代码变化:
下图可以看出,api
方式旋转是通过不断累加角度来完成,而非css3
中循环执行。

对比
通过上述两个小例子对比,无论是便捷度还是代码量,通过css3
来实现动画效果相对来说是更好的选择。api
方式存在较多局限性:
动画只能执行一次,循环效果需要通过定时器完成。
无法按照原有轨迹返回,需要返回必须定义定时器。
频繁借助定时器在性能上有硬伤。
综合以上,推荐通过css3
来完成动画效果。