图片叠加拖拽对比展示效果实现——Vue版
图片叠加拖拽对比展示效果实现——Vue版
项目中遇见一个需求:2张图片按竖线分割,左右两侧分别展示对应图片,通过滚动条拖动对应展示图片区域;
;
网上搜索了下,没有找到直接可用的组件,这里自己封装了一个次功能组件;后面会附上完整代码。,希望可以帮助到由此需求的小伙伴;
文章目录
- 图片叠加拖拽对比展示效果实现——Vue版
- 一、实现效果预览
- 二、HTML 部分
- 1. 组件包含:头部插槽、底部插槽、切换比较图片组
- 2. 代码示例
- 三、JS 部分
- 1. 包含组件传参,左侧图片地址、右侧图片地址、事件处理等
- 2. JS 部分代码如下:
- 四、 CSS 样式代码
- 六、完整使用示例
一、实现效果预览
二、HTML 部分
1. 组件包含:头部插槽、底部插槽、切换比较图片组
2. 代码示例
<template>
<div class="image-comparator">
<!-- 头部插槽 -->
<slot name="header"></slot>
<!-- 切换对比图片 下一组、上一组 -->
<div class="prev" @click="prevFun"><i class="el-icon-arrow-left"></i></div>
<div class="next" @click="nextFun"><i class="el-icon-arrow-right"></i></div>
<!-- 核心标签代码 -->
<div class="container" @mouseenter="startDrag" @mousemove="onDrag" @mouseup="endDrag" @mouseleave="endDrag">
<div class="image-wrapper"
:style="{ clipPath: `inset(0 ${100 - (dividerPosition / containerWidth * 100)}% 0 0)` }">
<img src="https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg" class="image"/>
</div>
<div class="divider" :style="{ left: `${dividerPosition}px` }"></div>
<div class="image-wrapper" :style="{ clipPath: `inset(0 0 0 ${(dividerPosition / containerWidth * 100)}%)` }">
<img src="https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg" class="image"/>
</div>
</div>
<!-- 底部插槽 -->
<slot name="footer"></slot>
</div>
</template>
三、JS 部分
1. 包含组件传参,左侧图片地址、右侧图片地址、事件处理等
2. JS 部分代码如下:
<script>
export default {
name: 'imageComparator',
props: {
leftImgUrl: {
type: String,
},
rightImgUrl: {
type: String,
},
},
data() {
return {
containerWidth: 500,
dividerPosition: 250,
dragging: false,
containerRect: null,
};
},
methods: {
updateContainerWidth() {
this.containerWidth = this.$el.querySelector('.container').clientWidth;
},
startDrag(event) {
this.dragging = true;
this.containerRect = this.$el.querySelector('.container').getBoundingClientRect();
},
onDrag(event) {
if (this.dragging && this.containerRect) {
let newPosition = event.clientX - this.containerRect.left;
if (newPosition < 0) newPosition = 0;
if (newPosition > this.containerRect.width) newPosition = this.containerRect.width;
this.dividerPosition = newPosition;
}
},
endDrag() {
this.dragging = false;
this.containerRect = null;
},
prevFun() {
this.$emit('prevFun');
},
nextFun() {
this.$emit('nextFun');
},
},
mounted() {
this.updateContainerWidth();
window.addEventListener('resize', this.updateContainerWidth);
},
beforeDestroy() {
window.removeEventListener('resize', this.updateContainerWidth);
},
};
</script>
四、 CSS 样式代码
<style scoped lang="less">
.image-comparator {
width: 90%;
/*max-width: 600px;*/
margin: 0 auto;
.container {
position: relative;
width: 100%;
height: 600px;
overflow: hidden;
}
.image-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.divider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background-color: black;
cursor: ew-resize;
z-index: 10;
}
.prev, .next {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 100;
cursor: pointer;
font-size: 40px;
color: white;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 50%;
transition: all 0.3s ease;
left: 10px;
&:hover {
background-color: rgba(0, 0, 0, 0.8);
color: #0bf4cb;
}
&.next {
right: 10px;
left: auto;
}
}
}
</style>
## 五、总结
本文着重介绍了Vue2 封装的图片分割展示组件,如果小伙伴项目是V3 可以自行修改Vue 组件即可,还有写组件传参地方,需要的话自行改为动态参数即可,这里父组件不做过多介绍,以免浪费小伙伴看代码时间;
六、完整使用示例
以下是一个完整的 代码示例
<template>
<div class="image-comparator">
<!-- 头部插槽 -->
<slot name="header"></slot>
<!-- 切换对比图片 下一组、上一组 -->
<div class="prev" @click="prevFun"><i class="el-icon-arrow-left"></i></div>
<div class="next" @click="nextFun"><i class="el-icon-arrow-right"></i></div>
<!-- 核心标签代码 -->
<div class="container" @mouseenter="startDrag" @mousemove="onDrag" @mouseup="endDrag" @mouseleave="endDrag">
<div class="image-wrapper"
:style="{ clipPath: `inset(0 ${100 - (dividerPosition / containerWidth * 100)}% 0 0)` }">
<img src="https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg" class="image"/>
</div>
<div class="divider" :style="{ left: `${dividerPosition}px` }"></div>
<div class="image-wrapper" :style="{ clipPath: `inset(0 0 0 ${(dividerPosition / containerWidth * 100)}%)` }">
<img src="https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg" class="image"/>
</div>
</div>
<!-- 底部插槽 -->
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'imageComparator',
props: {
leftImgUrl: {
type: String,
},
rightImgUrl: {
type: String,
},
},
data() {
return {
containerWidth: 500,
dividerPosition: 250,
dragging: false,
containerRect: null,
};
},
methods: {
updateContainerWidth() {
this.containerWidth = this.$el.querySelector('.container').clientWidth;
},
startDrag(event) {
this.dragging = true;
this.containerRect = this.$el.querySelector('.container').getBoundingClientRect();
},
onDrag(event) {
if (this.dragging && this.containerRect) {
let newPosition = event.clientX - this.containerRect.left;
if (newPosition < 0) newPosition = 0;
if (newPosition > this.containerRect.width) newPosition = this.containerRect.width;
this.dividerPosition = newPosition;
}
},
endDrag() {
this.dragging = false;
this.containerRect = null;
},
prevFun() {
this.$emit('prevFun');
},
nextFun() {
this.$emit('nextFun');
},
},
mounted() {
this.updateContainerWidth();
window.addEventListener('resize', this.updateContainerWidth);
},
beforeDestroy() {
window.removeEventListener('resize', this.updateContainerWidth);
},
};
</script>
<style scoped lang="less">
.image-comparator {
width: 90%;
/*max-width: 600px;*/
margin: 0 auto;
.container {
position: relative;
width: 100%;
height: 600px;
overflow: hidden;
}
.image-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.divider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background-color: black;
cursor: ew-resize;
z-index: 10;
}
.prev, .next {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 100;
cursor: pointer;
font-size: 40px;
color: white;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 50%;
transition: all 0.3s ease;
left: 10px;
&:hover {
background-color: rgba(0, 0, 0, 0.8);
color: #0bf4cb;
}
&.next {
right: 10px;
left: auto;
}
}
}
</style>
看到这里的小伙伴,欢迎点赞、评论,收藏!
如有前端相关疑问,请评论区留言,博主会在第一时间解答!!!