这是APP只有5个图
这是ITEM
slider html部分
export default {
name: 'ic-slider',
props: {
autoplay: Number,
showIndicators: {
type: Boolean,
default: true
},
duration: {
type: Number,
default: 500
}
},
data() {
return {
width: 0,
offset: 0,
startX: 0,
startY: 0,
active: 0,
deltaX: 0,
swipes: [],
direction: '',
currentDuration: 0
};
},
mounted() {
this.initialize();
// 监听 resize事件,改变窗口重新初始化
window.addEventListener('resize', () => {
this.initialize();
})
},
destroyed() {
clearTimeout(this.timer);
},
watch: {
swipes() {
this.initialize();
}
},
computed: {
count() {
return this.swipes.length;
},
trackStyle() {
return {
paddingLeft: this.width + 'px',
width: (this.count + 2) * this.width + 'px',
transitionDuration: `${this.currentDuration}ms`,
transform: `translate3d(${this.offset}px, 0, 0)`
};
},
activeIndicator() {
return (this.active + this.count) % this.count;
}
},
methods: {
initialize() {
clearTimeout(this.timer);
this.width = this.$el.getBoundingClientRect().width;
this.active = 0;
this.currentDuration = 0;
this.offset = this.count > 1 ? -this.width : 0;
this.swipes.forEach(swipe => {
swipe.offset = 0;
});
// this.autoPlay();
},
onTouchStart(event) {
clearTimeout(this.timer);
this.deltaX = 0;
this.direction = '';
this.currentDuration = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
if (this.active <= -1) {
this.move(this.count);
}
if (this.active >= this.count) {
this.move(-this.count);
};
// console.log('start:'+this.deltaX)
console.log('active:'+this.active)
},
onTouchMove(event) {
this.direction = this.direction || this.getDirection(event.touches[0]);
if (this.direction === 'horizontal') {
event.preventDefault();
this.deltaX = event.touches[0].clientX - this.startX;
this.move(0, this.range(this.deltaX, [-this.width, this.width]));
// console.log(this.deltaX+'deltaX'+'active:'+this.active);
}
},
onTouchEnd() {
if (this.deltaX) {
this.move(Math.abs(this.deltaX) > 50 ? (this.deltaX > 0 ? -1 : 1) : 0);
this.currentDuration = this.duration;
}
console.log(this.deltaX)
// this.autoPlay();
},
move(move = 0, offset = 0) {
const { active, count, swipes, deltaX, width } = this;
if (move) {
if (active === -1) {//初始值
swipes[count - 1].offset = 0;
}
swipes[0].offset = active === count - 1 && move > 0 ? count * width : 0;
this.active += move;
} else {
if (active === 0) {//第一个
swipes[count - 1].offset = deltaX > 0 ? -count * width : 0;
} else if (active === count - 1) {//最后一个
swipes[0].offset = deltaX < 0 ? count * width : 0;
}
}
this.offset = offset - (this.active + 1) * this.width;
// console.log(this.swipes.length+'===length')
},
autoPlay() {
const { autoplay } = this;
if (autoplay && this.count > 1) {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.currentDuration = 0;
if (this.active >= this.count) {
this.move(-this.count);
}
setTimeout(() => {
this.currentDuration = this.duration;
this.move(1);
this.autoPlay();
}, 30);
console.log(this.count+' '+this.width)
}, autoplay);
}
},
getDirection(touch) {
const distanceX = Math.abs(touch.clientX - this.startX);
const distanceY = Math.abs(touch.clientY - this.startY);
return distanceX > distanceY ? 'horizontal' : distanceX < distanceY ? 'vertical' : '';
},
range(num, arr) {
return Math.min(Math.max(num, arr[0]), arr[1]);
}
}
};
</script>
仔细看了下,这个实现很巧妙,他没有在前后添加图片。
我描述下他的做法。
[0],1,2,3,4
中括号表示视口,即当前看见0。如果此时从左向右滑动(slider整体移动),将4的transform设置为
-count * width
,即移到0的左侧,使用户可以看到4从左侧出现;反之4恢复translate(0)
;最右侧同理。
具体实现代码如下