小程序animation使用
想实现一个item左滑展示编辑和删除按钮的功能,涉及到元素移动,因此使用animation属性来实现
了解animation
下面这段代码设置了一个动画的各种属性(持续1000ms ; 匀速到加速再减速; 立即开始执行;元素变换基点,此处是平移,不起作用),然后设置动画效果向左平移100元素,最后,调用 export()
方法导出动画数据,并将其赋值给 animation
属性,从而触发视图的更新
html
<view class="box" animation="{{animationData}}">动画效果</view>
css
Page({ data: { animationData: {} }, onLoad: function() { // 创建一个动画实例 let animation = wx.createAnimation({ duration: 1000, // 动画持续时间 timingFunction: 'ease', // 动画效果,可选值有:linear、ease、ease-in、ease-in-out、ease-out、step-start、step-end delay: 0, // 延迟多长时间后开始动画 transformOrigin: '50% 50% 0' // 动画原点,用于指定动画相对于哪个点进行变换,默认值为"50% 50% 0" }); // 设置动画效果 animation.translate(-100).step(); // 更新数据,触发视图更新 this.setData({ animationData: animation.export() }); } });
动画各属性详解:
duration:动画执行完所有操作的需要的时间,毫秒
timingFunction
属性用于指定动画的时间曲线,决定了动画在播放过程中的变化速度。常见的取值包括:
-
linear
(线性):动画效果匀速进行,没有加速度或减速度,动画变化率保持恒定。 -
ease
(匀速到加速再减速):动画从匀速开始,然后逐渐加速,最后减速停止。这是一个常用的默认值,也是很多动画库的默认效果。 -
ease-in
(加速):动画从开始时较慢,然后逐渐加速到结束。在开始时速度较慢,逐渐加快。 -
ease-out
(减速):动画从开始时较快,然后逐渐减速直至结束。在结束时速度较慢,逐渐减慢。 -
ease-in-out
(加速再减速):动画从开始时较慢,然后逐渐加速,到达中间时速度最快,然后逐渐减速直至结束。 -
step-start
(分步开始):动画在每一帧都会直接跳跃到结束位置,但在两个关键帧之间没有动画效果。 -
step-end
(分步结束):动画在每一帧都会直接跳跃到开始位置,但在两个关键帧之间没有动画效果。
delay:多长时间后开始动画效果,毫秒
实现代码
<view> <view wx:for="{{tagDetail.goodsList}}" wx:key="id" class='itemContainer'> <view class="myItem" animation="{{item.itemAnimation}}" bindtouchstart='onTouchStart' bindtouchmove='onTouchMove' bindtouchend='onTouchEnd' id="{{index}}"> {{item.goodsName}} </view> <view class='menu'> <view id='{{item.id}}' class='menu-delete' bindtap='onDeleteMsgTap' bindlongtap='onDeleteMsgLongtap'> <text>删除</text> </view> <view id='{{item.id}}' class='menu-edit' bindtap='onMarkMsgTap' bindlongtap='onMarkMsgLongtap'> <text>编辑</text> </view> </view> </view> </view>
moveX: 0, //记录平移距离 showState: 0, //0 未显示菜单 1显示菜单 maxMoveLeft: 195, //消息列表项最大左滑距离 correctMoveLeft: 80, //菜单自动展示的左滑距离 lastAnimationId: "0", onTouchStart: function(e) { if (this.showState === 0) { // 未展示菜单,移动距离从0计算 this.moveX = 0; } else { // 已展示菜单 // 与上次操作的同一item,移动距离从 -this.maxMoveLeft 计算 if (e.currentTarget.id == this.lastAnimationId) { this.moveX = -this.maxMoveLeft } else { // 与上次操作的不同item, 移动距离从0开始计算 this.moveX = 0 } } this.firstTouchX = e.touches[0].clientX; this.translateXMsgItem(e.currentTarget.id, this.moveX, 200); }, onTouchMove: function(e) { var moveX = e.touches[0].clientX - this.firstTouchX; if (this.showState === 1) { // 和上次操作不是同一个item,关闭上次的item if (e.currentTarget.id != this.lastAnimationId) { this.translateXMsgItem(this.lastAnimationId, 0, 200); } else { // 和上次操作的同一个item, 移动距离需要从-this.maxMoveLeft 开始算 moveX = -this.maxMoveLeft + moveX } } //处理边界情况 if (moveX > 0) { moveX = 0; } //检测最大左滑距离 if (moveX < -this.maxMoveLeft) { moveX = -this.maxMoveLeft; } this.moveX = moveX; this.translateXMsgItem(e.currentTarget.id, moveX, 0); }, onTouchEnd: function(e) { if (this.moveX >= -this.correctMoveLeft) { this.moveX = 0; this.showState = 0 } else { this.moveX = -this.maxMoveLeft this.showState = 1 } let currentId = e.currentTarget.id this.translateXMsgItem(currentId, this.moveX, 500); this.lastAnimationId = currentId }, translateXMsgItem: function(id, x, duration) { var animation = wx.createAnimation({duration:duration}); animation.translateX(x).step(); var indexString = 'tagDetail.goodsList['+id+'].itemAnimation' this.setData({ [indexString]: animation.export() }) }
.itemContainer { width: 100%; height: 150rpx; border-bottom: 1rpx solid rgb(109, 21, 21); position: relative; left: 0; top: 0; overflow: hidden; } .myItem { position: absolute; width: 100%; height: 150rpx; left: 0; top: 0; z-index: 100; background-color: rgb(231, 188, 188); } .menu { display: flex; position: absolute; width: 100%; height: 150rpx; left: 0; top: 0; z-index: 0; color: #fff; text-align: center; } .menu-delete { position: absolute; width: 60px; height: 148rpx; top: 1rpx; right: 0; background-color: rgb(255, 58, 50); line-height: 150rpx; } .menu-edit { position: absolute; width: 60px; height: 148rpx; top: 1rpx; right: 60px; background-color: rgb(54, 128, 70); line-height: 150rpx; }
猪猪侠要努力呀!