小程序要做自动滚播而且可以点击可以拉动的效果,我尝试过几种方案都没有达到很好的效果...
1.scroll-view + setInterval
这种方法最简单粗暴,使用小程序自带的滑动元素再加上setInterval定时让滚动条移动,做出的一个滑动效果。
index.wxml:
<view class="demo">
<scroll-view
class="scrollView"
scroll-x="{{true}}"
scroll-left="{{left}}"
>
<view
class="scrollItem"
wx:for="{{itemList}}"
wx:for-index="index"
wx:for-item="item"
wx:key="{{index}}"
bindtap="showTips"
>
{{item}}
</view>
</scroll-view>
</view>
index.wxss:
.demo {
padding: 20px 0;
}
.demo .scrollView {
white-space: nowrap;
}
.demo .scrollView .scrollItem{
display: inline-block;
background: red;
margin: 20rpx;
width: 200px;
height: 200px;
}
index.js
const app = getApp()
Page({
data: {
itemList: [1, 2, 3, 4, 5, 6],
left: 0,
},
onShow() {
setInterval(() => {
this.setData({
left: this.data.left +=1,
})
}, 100)
},
showTips() {
console.log('点击~');
}
})
效果(没有动图):
这样你就得到了一个有缓慢向左移动的滚播
但是
因为你需要短时间去调用setData来刷新视图,这样会让你页面上dom操作都无法被触发,所以当你点击 showTips时是不会有任何反应。
这个方法不建议使用。
2.animation
这种方法是获取元素的宽度计算出需要滑动的长度,然后使用小程序动画效果。
index.wxml:
<!--index.wxml-->
<view class="demo">
<view
class="scrollView"
>
<view
id="box"
animation="{{animationData}}"
>
<view
class="scrollItem"
wx:for="{{itemList}}"
wx:for-index="index"
wx:for-item="item"
wx:key="{{index}}"
bindtap="showStop"
>
{{item}}
</view>
</view>
</view>
</view>
index.wxss:
/**index.wxss**/
.demo {
padding: 20px 0;
}
.demo .scrollView {
white-space: nowrap;
/* 不是 srcoll-view 需要加上滚动条 */
overflow-x: auto;
}
.demo .scrollView .scrollItem{
display: inline-block;
background: red;
margin: 20rpx;
width: 200px;
height: 200px;
}
#box {
display: inline-block;
background: rgb(0, 0, 0);
}
index.js
const app = getApp()
Page({
data: {
itemList: [1, 2, 3, 4, 5, 6],
/**
* 通过 wx.createSelectorQuery().select() 方法动态获取
*/
width: 0,
animationData: {},
},
onLoad() {
wx.createSelectorQuery().select('#box').boundingClientRect().exec(res => {
// 时间
let duration = 3000;
let animation = wx.createAnimation({
duration
});
// 手机宽度
let phoneWidth = wx.getSystemInfoSync().windowWidth;
let moveLeng = - res[0].width + phoneWidth;
animation.translateX(moveLeng).step();
this.setData({
animationData: animation.export(),
});
console.log(res);
})
},
showStop() {
console.log('停止动画');
// 停止动作
wx.createSelectorQuery().select('#box').boundingClientRect().exec(res => {
var animation = wx.createAnimation({
duration: 0,
});
// 停在当前位置
animation.translateX(res[0].left).step();
this.setData({
animationData: animation.export(),
});
});
}
})
这种方法可以流畅滚动并且可以触发事件,可以触发事件就可以去做点播的停止和其他操作
但是
当这个动画滑动完成或者你中途停止动画,会发现移动的部分已经是超出了浏览器以外,没办法再滑动回来,因为动画的滑动是定位滑动直接把元素定位到外部了。
3.(view + animation) + srcoll-view
经过上面两次失败的尝试得到两个想法,animation实现滑动动作非常好用,scroll-view用于实现左右滑动,那么就可以结合这两个各司其职(感觉做法好蠢)。
思路:建两个模块滑动时显示view + anomatiom,暂停时隐藏掉,显示srcoll-view给用户滑动,一个相互切换的过程。
index.wxml:
<!--index.wxml-->
<view class="demo">
<view
class="scrollView"
>
<!-- 动作模块 -->
<view
id="box-animation"
animation="{{animationData}}"
wx:if="{{isShow}}"
>
<view
class="scrollItem"
wx:for="{{itemList}}"
wx:for-index="index"
wx:for-item="item"
wx:key="{{index}}"
bindtap="showStop"
>
{{item}}
</view>
</view>
<!-- 滑动模块 -->
<scroll-view
scroll-x="true"
id="box-scroll"
wx:if="{{!isShow}}"
scroll-left="{{scrollLeft}}"
>
<view
class="scrollItem"
wx:for="{{itemList}}"
wx:for-index="index"
wx:for-item="item"
wx:key="{{index}}"
bindtap="showStop"
>
{{item}}
</view>
</scroll-view>
</view>
</view>
index.wxss:
/**index.wxss**/
.demo {
padding: 20px 0;
}
.demo .scrollView {
white-space: nowrap;
overflow-y: hidden;
width: 100%;
}
.demo .scrollView .scrollItem{
display: inline-block;
background: red;
margin: 20rpx;
width: 200px;
height: 200px;
}
#box-animation {
display: inline-block;
white-space: nowrap;
background: rgb(0, 0, 0);
/* 不需要显示滑动 */
position: fixed;
}
#box-scroll {
display: inline-block;
white-space: nowrap;
background: rgb(0, 0, 0);
}
index.js:
const app = getApp()
Page({
data: {
itemList: [1, 2, 3, 4, 5, 6],
width: 0,
animationData: {},
isShow: true,
scrollLeft: 0,
},
onLoad() {
this.animationFun();
},
animationFun() {
wx.createSelectorQuery().select('#box-animation').boundingClientRect().exec(res => {
// 时间
let duration = 10000;
let animation = wx.createAnimation({
duration
});
// 手机宽度
let phoneWidth = wx.getSystemInfoSync().windowWidth;
let moveLeng = - res[0].width + phoneWidth;
animation.translateX(moveLeng).step();
this.setData({
animationData: animation.export(),
});
})
},
showStop() {
console.log('停止动画');
// 停止动作
wx.createSelectorQuery().select('#box-animation').boundingClientRect().exec(res => {
var animation = wx.createAnimation({
duration: 0,
});
// 停在当前位置
animation.translateX(res[0].left).step();
this.setData({
animationData: animation.export(),
// 切换并让scoll-view定位到对于位置
isShow: false,
scrollLeft: - res[0].left,
});
});
}
})
总结
做这个效果最理想的方法应该是只用一个模块利用js去控制滑动和停止,但是最终用了第三种方法去实现,用这种方法实现出来对自己很不满意的,后续如果有更好的方案会补充,希望有小伙伴有更好方案可以提供给我参考参考...