需求是酱紫的:
页面顶部的喇叭通知,内容不固定,宽度不固定,就是做走马灯(轮播)效果,从左到右的走马灯(轮播),每播放一遍暂停 1500ms ~ 2000ms
刚开始想的是 css 的 position: relative + animation,如果宽度固定还好说,宽度不固定,用百分比的话,想象很美好,现实很骨感,百分比相对的是父元素宽度…,所以 pass 掉
又想到动态生成 keyframes ,这样动态获取子元素宽度,再动态生成 keyframes ,动态传入 偏移量,这样就好了,可是这是小程序…,如果web端倒是可以动态操作 cssRule,小程序端,我真不会
然后从小程序文档直接搜索 animation ,还真找到了
Animation API
于是就理所当然的用上啦
看结果
不唠叨,直接点击查看代码片段:https://developers.weixin.qq.com/s/Ju3T3amk7oKc
思路:
页面结构
<view class="integral-notice common-flex-between">
<view class="integral-notice-left">
<image class="integral-notice-left-icon" src="icon-horn.png" mode="aspectFill"></image>
</view>
<view class="integral-notice-right common-flex-start">
<view class="integral-notice-right-item notice_1" animation="{{animationData}}">各位憧橙会员大家好,积分商城发货周期为一个月2次,每个月15号和30号发货,有问题请联系客服,谢谢!</view>
<!-- 这里之所以放两个一样的,是为了无缝衔接的滚动 -->
<view class="integral-notice-right-item notice_1" animation="{{animationData}}">各位憧橙会员大家好,积分商城发货周期为一个月2次,每个月15号和30号发货,有问题请联系客服,谢谢!</view>
</view>
</view>
样式代码
/*通用flex水平方向垂直居中布局*/
.common-flex-between {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
}
.common-flex-around {
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: nowrap;
}
.common-flex-center {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
}
.common-flex-start {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
}
.integral-notice{
position: fixed;
left: 0;
top: 0;
background: #FEF6F0;
width: 750rpx;
height: 98rpx;
box-sizing: border-box;
padding-left: 24rpx;
padding-right: 24rpx;
}
.integral-notice-left{
box-sizing: border-box;
padding-right: 20rpx;
}
.integral-notice-left-icon{
display: block;
width: 38rpx;
height: 34rpx;
}
.integral-notice-right{
overflow: hidden;
}
.integral-notice-right-item{
white-space: nowrap;
color: #141418;
font-size: 28rpx;
letter-spacing: 2rpx;
height: 32rpx;
line-height: 34rpx;
position: relative;
left: 0;
top: 0;
}
第一步: 让它动起来
js代码
/**
* 页面的初始数据
*/
data: {
animationData: {},
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
const query = wx.createSelectorQuery()
query.selectAll('.notice_1').boundingClientRect((res)=>{
let noticeWidth = res[0].width
this.startAnimation(noticeWidth)
})
query.exec()
},
startAnimation(left, duration = 10000) {
this.animation = wx.createAnimation()
let offset = -left
this.animation.left(offset).step({
duration,
timingFunction: 'linear'
})
this.setData({
animationData: this.animation.export()
})
},
备注
:这里你会发现,是动起来了,就执行了一次
木事,改代码,让它执行完的时候回到起点
startAnimation(left, duration = 10000) {
this.animation = wx.createAnimation()
let offset = -left
this.animation.left(offset).step({
duration,
timingFunction: 'linear'
})
this.setData({
animationData: this.animation.export()
})
// 这里,让它回去起点,便于后边无限循环
setTimeout(() => {
this.animation.left(0).step({
duration: 0, // 时间为 0
timingFunction: 'step-start' // 这个是 动画第一帧就跳至结束状态直到结束
})
this.setData({
animationData: this.animation.export()
})
}, duration)
},
看到这里,无限循环播放的动画就知道怎么做了吧,做个递归不就好啦?不信咱试试?
startAnimation(left, duration = 10000) {
this.animation = wx.createAnimation()
let offset = -left
this.animation.left(offset).step({
duration,
timingFunction: 'linear'
})
this.setData({
animationData: this.animation.export()
})
setTimeout(() => {
this.animation.left(0).step({
duration: 0,
timingFunction: 'step-start'
})
this.setData({
animationData: this.animation.export()
})
// 递归,无限循环播放
this.startAnimation(left, duration)
}, duration)
},
注意
:你会发现时好时坏,没事,加延迟,加异步,因为虽然是同步执行的代码,代码执行+运行也要时间啊,1ms、5ms、10ms 也是时间
startAnimation(left, duration = 10000, wait = 2000) {
this.animation = wx.createAnimation()
let offset = -left
this.animation.left(offset).step({
duration,
timingFunction: 'linear'
})
this.setData({
animationData: this.animation.export()
})
setTimeout(() => {
this.animation.left(0).step({
duration: 0,
timingFunction: 'step-start'
})
this.setData({
animationData: this.animation.export()
})
// 加上延迟,加上需求上的等待时间 wait
let minWait = 12 // 之所以给了个 minWait,是防止 bug,就是那个代码执行/运行时间,经测试,我这里 12ms 的延迟比较合适
setTimeout(() => {
this.startAnimation(left, duration, wait)
}, wait < minWait ? minWait : wait)
}, duration)
},
欧啦,大功告成,