小程序-源码实现3D层叠轮播图
作者:fengfanv
Tips:
- 此文如果对您有帮助,希望
客官您可以施舍个赞或评论,让更多的人看到。
Demo的由来:
- 1、小程序里无法使用
swiper.js插件 - 2、网上搜索关于小程序层叠轮播,但得到的结果达不到想要的效果
Demo源码:
- demo.wxml
<!--轮播图辅助线-->
<view class="line">
<view></view>
</view>
<!--轮播图本体-->
<view class="selection_cards" bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend">
<view class="selection_cards_item" wx:for="{{list}}" wx:key="index"
style="left:{{item.style.left}}px; z-index:{{item.style.zIndex}}; transform:{{item.style.transform}}; opacity:{{item.style.opacity}}; transition:{{!isTouch?'0.1s':0}};">
{{item.option}}
</view>
</view>
- demo.wxss
/*轮播图辅助线,css*/
.line{
width: 100%;
height: 420rpx;
border: 1rpx solid red;
position: fixed;
left: 0;
top: 434rpx;
z-index: 0;
}
.line view{
width: 213rpx;
height: 420rpx;
/* border: 1rpx solid red; */
border-left: 1rpx solid red;
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
top: 0;
z-index: 0;
}
/*层叠轮播选牌,css*/
.selection_cards{
width: 100%;
height: 400rpx;
position: relative;
margin-top: 200px;
z-index: 99;
}
.selection_cards_item{
width: 194rpx;/*188*/
height:350rpx;/*340*/
background:green;
background-size: 100%;
border-radius: 16rpx;
position: absolute;
top: 0;
color: white;
font-size: 100rpx;
box-sizing: border-box;
border: 4rpx solid black;
}
- demo.js
Page({
data: {
cardNumber: 7, //牌的数量
indexArr: [-3, -2, -1, 0, 1, 2, 3], //牌的坐标,0就是最中间那张牌
list: [], //用于渲染的列表
listArr: [], //备份初始化后的list数组
isTouch: false, //当前是否为触摸状态
startPageX: 0, //按下触摸时的位置
cardWidth: 0, //当前设备下 牌的真实宽度
screenWidth: 0, //当前屏幕的真实宽度
},
onLoad() {
let _this = this;
_this.init();
},
/*层叠轮播图初始化方法*/
init: function () {
let _this = this;
wx.getSystemInfo({
success(res) {
//获取设备信息成功
let cardWidth = res.screenWidth / 750 * 194;
//1、初始化用于渲染的数组
let len = _this.data.cardNumber;
let arr = [];
for (let i = 0; i < len; i++) {
let item = {
option: 0, //自定义参数
left: (i * (cardWidth / 2)),
scale: (3 - Math.abs(_this.data.indexArr[i])) * 0.4,
zIndex: 3 - Math.abs(_this.data.indexArr[i]),
style: {
left: (i * (cardWidth / 2)),
transition: 0,
zIndex: 3 - Math.abs(_this.data.indexArr[i]),
transform: "scale(" + ((3 - Math.abs(_this.data.indexArr[i])) * 0.4) + ")",
opacity: (3 - Math.abs(_this.data.indexArr[i]) != 0) ? 1 : 0
}
}
item.option = i;
arr.push(item);
}
console.log(arr);
_this.setData({
screenWidth: res.screenWidth,
cardWidth,
list: arr,
listArr: arr
})
}
})
},
/*事件,触摸开始*/
touchstart(e) {
this.setData({
startPageX: e.changedTouches[0].pageX,
isTouch: true //开始触摸
});
},
/*事件,触摸移动*/
touchmove(e) {
let _this = this;
let pageX = e.changedTouches[0].pageX;
let move = pageX - _this.data.startPageX; //正数,向右滑动;负数,向左滑动
let list = JSON.parse(JSON.stringify(_this.data.list));
let len = list.length;
if (move > 0) { //向右滑
for (let i = 0; i < len; i++) {
//1、改变每张牌的位置
list[i].style.left = list[i].left + ((move) * 0.52);
//2、处理7张牌里,左边牌的样式,不包括中间的牌(坐标:-3,-2,-1)
if (_this.data.indexArr[i] < 0) {
list[i].style.transform = "scale(" + (list[i].scale + (move * 0.005)) + ")";
list[i].style.zIndex = list[i].zIndex + 1;
if (_this.data.indexArr[i] >= -3) {
list[i].style.opacity = 1; //把最左边的牌显示
}
} else {
//3、处理7张牌里,右边牌的样式,包括中间的牌(坐标:0,1,2,3)
list[i].style.transform = "scale(" + (list[i].scale - (move * 0.005)) + ")";
list[i].style.zIndex = list[i].zIndex - 1;
if (_this.data.indexArr[i] >= 2) {
list[i].style.opacity = 0; //把最右边的牌关闭
}
}
}
//检查,向右滑动时,滑动的距离,可不可以,切换牌的位置
//原理,改变option(自定义参数)的位置
if (list[2].style.left >= list[3].left) {
//console.log('可以切换牌的位置');
let newList = [];
for (let i = 0; i < len; i++) {
let index = i; //当前牌,将要变成哪一个牌的位置
if (i + 1 != len) {
index = i + 1;
} else {
//最后的那张牌,到,第一张牌的位置
index = 0;
}
let currentOption = list[i].option;
// console.log('currentOption',currentOption);
// console.log('list[i].option',list[i].option);
let item = _this.data.listArr[index];
item.option = currentOption;
newList[index] = item;
}
list = newList;
_this.setData({
startPageX: pageX
});
}
_this.setData({
list
})
} else { //向左滑
for (let i = 0; i < len; i++) {
//1、改变每张牌的位置
list[i].style.left = list[i].left + ((move) * 0.52);
//2、处理7张牌里,左边牌的样式,包括中间的牌(坐标:-3,-2,-1,0)
if (_this.data.indexArr[i] <= 0) {
list[i].style.transform = "scale(" + (list[i].scale - Math.abs(move * 0.005)) + ")";
list[i].style.zIndex = list[i].zIndex - 1;
if (_this.data.indexArr[i] <= -2) {
list[i].style.opacity = 0; //最左边的牌消失
}
} else {
//3、处理7张牌里,右边牌的样式,不包括中间的牌(坐标:1,2,3)
list[i].style.transform = "scale(" + (list[i].scale + Math.abs(move * 0.005)) + ")";
list[i].style.zIndex = list[i].zIndex + 1;
if (_this.data.indexArr[i] >= 2) {
list[i].style.opacity = 1; //最右边的牌显示
}
}
}
//检查,向左滑动时,滑动的距离,可不可以,切换牌的位置
//原理,改变option(自定义参数)的位置
if (list[3].style.left <= list[2].left) {
//console.log('可以切换牌的位置');
let newList = [];
for (let i = 0; i < len; i++) {
let index = i; //当前牌,将要变成哪一个牌的位置
if (i == 0) {
index = len - 1;
} else {
//最后一个元素到第一个元素的位置
index = i - 1;
}
let currentOption = list[i].option;
// console.log('currentOption',currentOption);
// console.log('list[i].option',list[i].option);
let item = _this.data.listArr[index];
item.option = currentOption;
newList[index] = item;
}
list = newList;
_this.setData({
startPageX: pageX
});
}
_this.setData({
list
})
}
},
/*事件,触摸结束*/
touchend(e) {
let _this = this;
let list = JSON.parse(JSON.stringify(_this.data.list));
let len = list.length;
_this.setData({
isTouch: false //关闭触摸
});
//检测可不可以切换牌的位置
if (list[2].style.left >= list[3].left || list[3].style.left <= list[2].left) {
//console.log('可以切换牌的位置');
} else {
//移动的距离不够,不用切换牌的位置,恢复牌的位置
for (let i = 0; i < len; i++) {
list[i].style.left = list[i].left;
list[i].style.zIndex = list[i].zIndex;
list[i].style.transform = "scale(" + list[i].scale + ")";
list[i].style.opacity = (3 - Math.abs(_this.data.indexArr[i]) != 0) ? 1 : 0
}
_this.setData({
list
})
}
}
})