需求:两张图重叠放在一起,拖动分割线实现卷帘对比效果,如图
一、vue2代码
<template>
<div class="main">
<div class="img-comparison" @mousedown="startSlide">
<img class="before" src="../assets/images/white/1.png" alt="Before" />
<img
class="after"
src="../assets/images/white/2.png"
alt="After"
:style="{
clipPath:
'polygon(0 0, ' +
sliderPosition +
'% 0, ' +
sliderPosition +
'% 100%, 0 100%)',
}"
/>
<div class="slider" :style="{ left: sliderPosition + '%' }"></div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sliderPosition: 0, // 初始位置设为 0 (左侧)
isSliding: false,
};
},
methods: {
startSlide(e) {
this.isSliding = true;
document.addEventListener("mousemove", this.moveSlider);
document.addEventListener("mouseup", this.endSlide);
this.moveSlider(e);
// 禁止文本和图片选中
document.body.style.userSelect = "none";
},
moveSlider(e) {
if (!this.isSliding) return;
const comparisonRect = e.target
.closest(".img-comparison")
.getBoundingClientRect();
const newPosition = e.clientX - comparisonRect.left;
this.sliderPosition =
(Math.max(0, Math.min(comparisonRect.width, newPosition)) /
comparisonRect.width) *
100;
},
endSlide() {
this.isSliding = false;
document.removeEventListener("mousemove", this.moveSlider);
document.removeEventListener("mouseup", this.endSlide);
// 恢复文本和图片的可选中行为
document.body.style.userSelect = "";
},
},
};
</script>
<style lang="scss" scoped>
.main {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: black;
.img-comparison {
position: relative;
width: 100%;
max-width: 600px;
user-select: none; // 禁用选择
img {
width: 100%;
height: 600px;
pointer-events: none; // 禁止图片的鼠标事件,以避免选中
}
.after {
position: absolute;
top: 0;
left: 0;
transition: clip-path 0.3s ease; // 加快动画速度
}
.slider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background-color: rgba(255, 255, 255, 0.5);
cursor: ew-resize;
transition: left 0.3s ease; // 加快动画速度
}
}
.img-comparison:hover {
cursor: pointer;
}
}
</style>
二、uniapp代码
<template>
<view class="main">
<view class="img-comparison" @touchstart="startSlide" @touchmove="moveSlider" @touchend="endSlide">
<image class="before" :src="require('../../static/888.png')" mode="aspectFill" alt="Before"></image>
<image
class="after"
:src="require('../../static/999.png')"
mode="aspectFill"
:style="{
clipPath:
'polygon(0 0, ' +
sliderPosition +
'% 0, ' +
sliderPosition +
'% 100%, 0 100%)',
}"
alt="After"
></image>
<view class="slider" :style="{ left: sliderPosition + '%' }"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
sliderPosition: 0, // 初始位置设为 0 (左侧)
isSliding: false,
};
},
methods: {
startSlide(e) {
this.isSliding = true;
this.moveSlider(e);
},
moveSlider(e) {
if (!this.isSliding) return;
const query = uni.createSelectorQuery().in(this);
query.select('.img-comparison').boundingClientRect((res) => {
const newPosition = e.changedTouches[0].clientX - res.left;
this.sliderPosition =
(Math.max(0, Math.min(res.width, newPosition)) / res.width) * 100;
}).exec();
},
endSlide() {
this.isSliding = false;
},
},
};
</script>
<style lang="scss" scoped>
.main {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: black;
.img-comparison {
position: relative;
width: 100%;
max-width: 600px;
user-select: none; // 禁用选择
image {
width: 100%;
height: 600px;
pointer-events: none; // 禁止图片的鼠标事件,以避免选中
}
.after {
position: absolute;
top: 0;
left: 0;
transition: clip-path 0.3s ease; // 加快动画速度
}
.slider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background-color: rgba(255, 255, 255, 0.5);
cursor: ew-resize;
transition: left 0.3s ease; // 加快动画速度
}
}
.img-comparison:hover {
cursor: pointer;
}
}
</style>