微信小程序「Tower Swiper」组件, 小程序代码片段
#Arithmetic
position
, z-index
, margin-left
, transform
, transition
, opacity
throttle
, debounce
, wx.createSelectorQuery
(通过 child 计算容器高度)
touchstart
, touchmove
, touchend
tower-swiper
设置position: relative
tower-swiper-item
使用绝对布局position:absolute
使其再parent中水平居中的位置tower-swiper-item
通过transform:translateX()
实现水平(同样可以使用margin-left
,这里为了偏移量为自身宽度百分比,便使用了translateX
)tower-swiper-item
通过transform:scale()
实现尺寸层次感tower-swiper-item
通过z-index
实现堆叠效果,中间至两端的元素,z-index
递减tower-swiper-item
通过transition
实现过渡效果- 画重点: 通过
js
计算z-index
,left
偏移量z-index 从中间往两端依次降低,left偏移量中间为0, 左端为负值,右端为正值
- 通过
touchstart
,touchmove
,touchend
处理手势交互 - 性能优化: 通过
throttle
,debounce
过滤一些不必要的高频事件
.tower-swiper-item {
position: absolute;
top: 0;
left: 50%;
transform: translateX(calc(-50% + var(--left) * 20%));
z-index: var(--z-index);
transition: all ease 0.5s;
}
.tower-swiper-item--hidden {
opacity: 0;
}
.tower-swiper-item__scale {
transform: scale(var(--scale));
transition: all ease 0.5s;
}
const { _items, _active } = this.data;
const l = _items.length;
const odd = l % 2;
const half = Math.floor(_items.length / 2);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < _items.length; i++) {
const item = _items[(half + _active + i + odd) % l];
const zIndex = half - Math.abs(half - i) + odd;
item.setZIndex(zIndex);
item.setLeft(i - half);
item.setScale(1 - (half - zIndex) / 10);
}
通过设置 active 改变中间显示的 item
{
"usingComponents": {
"tower-swiper": "/lib/tower-swiper/index",
"tower-swiper-item": "/lib/tower-swiper-item/index"
}
}
<tower-swiper class="tower-swiper">
<tower-swiper-item wx:for="{{items}}" wx:key="id">
<image class="item" src="{{item.url}}" mode="aspectFill"></image>
</tower-swiper-item>
</tower-swiper>
Page({
data: {
items: [
{ id: 0, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg' },
{ id: 1, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84001.jpg' },
{ id: 2, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg' },
{ id: 3, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg' },
{ id: 4, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg' },
{ id: 5, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg' },
{ id: 6, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg' },
],
},
});