图片叠加拖拽对比展示效果实现——Vue版

图片叠加拖拽对比展示效果实现------Vue版

项目中遇见一个需求:2张图片按竖线分割,左右两侧分别展示对应图片,通过滚动条拖动对应展示图片区域; ;

网上搜索了下,没有找到直接可用的组件,这里自己封装了一个次功能组件;后面会附上完整代码。,希望可以帮助到由此需求的小伙伴;

文章目录

  • 图片叠加拖拽对比展示效果实现------Vue版
    • 一、实现效果预览
    • [二、HTML 部分](#二、HTML 部分)
      • [1. 组件包含:头部插槽、底部插槽、切换比较图片组](#1. 组件包含:头部插槽、底部插槽、切换比较图片组)
      • [2. 代码示例](#2. 代码示例)
    • [三、JS 部分](#三、JS 部分)
      • [1. 包含组件传参,左侧图片地址、右侧图片地址、事件处理等](#1. 包含组件传参,左侧图片地址、右侧图片地址、事件处理等)
      • [2. JS 部分代码如下:](#2. JS 部分代码如下:)
    • [四、 CSS 样式代码](#四、 CSS 样式代码)
    • 六、完整使用示例

一、实现效果预览

二、HTML 部分

1. 组件包含:头部插槽、底部插槽、切换比较图片组

2. 代码示例

html 复制代码
<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 部分代码如下:

javascript 复制代码
<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 样式代码

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 组件即可,还有写组件传参地方,需要的话自行改为动态参数即可,这里父组件不做过多介绍,以免浪费小伙伴看代码时间;

六、完整使用示例

以下是一个完整的 代码示例

javascript 复制代码
<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>

看到这里的小伙伴,欢迎点赞、评论,收藏!

如有前端相关疑问,请评论区留言,博主会在第一时间解答!!!

相关推荐
Setsuna_F_Seiei9 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲11 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能
默_笙11 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan12 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
kyriewen13 小时前
我扒了 10,221 条 JD:腾讯技术岗 75% 在要 AI
前端·人工智能·ai编程
郑州光合科技余经理13 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
+VX:Fegn089514 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
雪芽蓝域zzs14 小时前
第 7 章:双 Y 轴组合图(柱状 + 折线,看板高频场景)
vue.js·echars
IT_陈寒14 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端
一 乐14 小时前
二手交易平台|基于springboot + vue二手交易平台(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序