微信提供的动画API:wx.createAnimation
创建一个动画实例animation。调用实例的方法来描述动画。最后通过动画实例的
export
方法导出动画数据传递给组件的animation
属性。
注意:export
方法每次调用后会清掉之前的动画操作。
有四个可设置参数:
1.duration:动画持续时间,单位ms,默认400ms
2.delay:动画延迟时间,单位 ms,默认0ms
3.timingFunction:定义动画的效果,默认"linear",还有"ease"、"ease-in"、"ease-in-out" 等 【查看更多】
4.transformOrigin:设置动画的基点,默认"50% 50% 0"
动画队列
调用动画操作方法后要调用 step() 来表示一组动画完成,可以在一组动画中调用任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。step 可以传入一个跟 wx.createAnimation() 一样的配置参数用于指定当前组动画的配置。
1.先来一个简单的缩放动画热热身,比如我们点击收藏按钮时,收藏的图标先放大然后在变回原来大小的动画效果。
let param = {
goodsId: this.data.goodsId,
};
let goods = this.data.goodsNormal;
goods.favoriteFlag = flag == 1 ? 0 : 1;
app.request(func, param, function (res) {
if (res.code == 0) {
that.collectAnim.scale(1.5).step();
that.setData({
goodsNormal: goods,
collectAnim: that.collectAnim.export()
})
setTimeout(function () {
that.collectAnim.scale(1).step();
that.setData({
collectAnim: that.collectAnim.export()
})
}.bind(that), 1000);
}
});
2.点击上图的加入购物车或者马上购买,一般会从底部弹出一个选择商品规格的遮罩,背景变暗,其实现方式如下
wxml:
<view wx:if="{{showCover}}" class='cover-bg' catchtap='dismiss'></view>
<view wx:if="{{showCover}}" class='cover-show' animation='{{animationData}}'>
<image src='{{goodsNormal.specList[position].imageUrl}}' class='cover-image' catchtap='watchImage' />
<view class='cover-top'>
<text class='product-new-price'>¥{{coverPrice}}</text>
<text class='cover-text' style='margin-top:5rpx;'>已选:{{types}}</text>
</view>
<view class='divider_thin' style='margin-top:20rpx;'></view>
<view class='cover-center'>
<view style='padding:10rpx;'>选择类型</view>
<view wx:for="{{goodsNormal.specList}}" wx:for-item='type' data-position='{{index}}' class='{{position==index?"cover-type-select":"cover-type"}}' catchtap='typeSelect'>
{{type.name}}
</view>
</view>
<view class='cover-bottom'>
<text>数量(库存 {{goodsNormal.specList[position].qty}} 件)</text>
<view class='cover-bottom-counts'>
<image src='../../res/icon/sub.png' class='cover-bottom-image' catchtap='subCounts' />
<text class='cover-bottom-text'>{{pickCounts}}</text>
<image src='../../res/icon/add.png' class='cover-bottom-image' catchtap='addCounts' />
</view>
</view>
<view class='cover-sure' catchtap='makeSure'>
<text>确定</text>
</view>
</view>
wxss:
.cover-bg {
width: 100%;
height: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
opacity: 0.5;
z-index: 100;
overflow: hidden;
overflow-y: hidden;
}
.cover-show {
width: 100%;
height: 50%;
background: #fff;
z-index: 200;
position: fixed;
bottom: 0;
left: 0;
}
.cover-image {
width: 150rpx;
height: 150rpx;
position: absolute;
top: -50rpx;
left: 20rpx;
border-radius: 5rpx;
}
.cover-top {
display: flex;
flex-direction: column;
margin-left: 190rpx;
margin-top: 10rpx;
}
.cover-text {
font-size: 9pt;
color: #353535;
}
.cover-center {
font-size: 10pt;
color: #353535;
padding: 10rpx;
}
.cover-type {
background: #e6e6e6;
border-radius: 5rpx;
padding: 5rpx 10rpx;
margin: 10rpx;
display: inline-block;
}
.cover-type-select {
background: red;
border-radius: 5rpx;
padding: 5rpx 10rpx;
margin: 10rpx;
color: #fff;
display: inline-block;
}
.cover-bottom {
font-size: 10pt;
color: #353535;
padding: 20rpx;
margin-top: 30rpx;
margin-right: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.cover-bottom-counts {
display: flex;
justify-content: center;
align-items: center;
}
.cover-bottom-image {
width: 40rpx;
height: 40rpx;
}
.cover-bottom-text {
font-size: 12pt;
color: #353535;
padding: 15rpx;
min-width: 40rpx;
text-align: center;
}
.cover-sure {
width: 100%;
background: red;
color: #fff;
font-size: 12pt;
padding: 20rpx;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
}
js:
/**
* 马上购买动画
*/
buyNowAnim: function () {
let anim = wx.createAnimation({
duration: 200,
timingFunction: 'linear',
delay: 0,
});
anim.translateY(500).step();
this.setData({
animationData: anim.export(),
showCover: true,
});
setTimeout(function () {
anim.translateY(0).step();
this.setData({
animationData: anim.export()
});
}.bind(this), 200);
},
/**
* 隐藏遮罩
*/
dismiss: function () {
//console.log('dismiss: function');
let anim = wx.createAnimation({
duration: 200,
timingFunction: 'linear',
delay: 0,
});
anim.translateY(500).step();
this.setData({
animationData: anim.export(),
});
setTimeout(function () {
anim.translateY(0).step();
this.setData({
animationData: anim.export(),
showCover: false,
})
}.bind(this), 200);
},
效果图如下:
当点击外部时,遮罩向下滑动直至隐藏,灰色背景消失。
有个尤为突出的小问题是这个遮罩不能够完全拦截住触摸事件,事件会向下传递到底部视图,如果不作处理,当上下滑动遮罩区域的时候,下面的布局也会跟着滑动,这样就很不合理,解决方式是 找到最外部的根组件,当遮罩出现时为其添加overflow:hidden,遮罩隐藏时不添加。
.root {
width: 100%;
height: 100%;
}
.root-cover {
width: 100%;
height: 100%;
overflow: hidden;
}
<view class='{{showCover?"root-cover":"root"}}' >
...
...
</view>
这样问题完美解决。
还有一种实现动画效果的方式,就是通过css3里的 keyframes 来实现,如下筛选菜单:
@keyframes down {
from {
transform: translateY(0%);
}
to {
transform: translateY(100%);
}
}
.down {
display: block;
animation: down 0.1s ease-in both;
}
@keyframes up {
from {
transform: translateY(100%);
}
to {
transform: translateY(0%);
}
}
.up {
display: block;
animation: up 0.2s ease-in both;
}
/*半透明背景*/
.shadow {
width: 100%;
background: #000;
opacity: 0.5;
position: absolute;
z-index: 50;
top: 80rpx;
}
实现效果为:
That's all!