【Uniapp】图片修复对比组件

14 篇文章 0 订阅

效果图

在这里插入图片描述
不废话,直接上源码!

组件直接用

<template>
  <view
    class="img-comparison-container"
    :style="'width:' + width + 'rpx;height:' + height + 'rpx'"
  >
    <view class="before-image" :style="'width:' + x + 'rpx'">
      <view :style="'width:' + width + 'rpx;height:' + height + 'rpx'">
        <image
          :src="beforeImageUrl"
          class="images"
          mode="aspectFill"
          data-type="before"
          @tap="previewImage"
        />
      </view>
      <view v-if="beforeText" class="before-text">
        {{ beforeText }}
      </view>
    </view>
    <view class="after-image">
      <view :style="'width:' + width + 'rpx;height:' + height + 'rpx'">
        <image
          :src="afterImageUrl"
          class="images"
          mode="aspectFill"
          data-type="after"
          @tap="previewImage"
        />
      </view>
      <view v-if="afterText" class="after-text">
        {{ afterText }}
      </view>
    </view>
    <view
      class="slider-bar"
      :style="'left:' + x + 'rpx'"
      @touchmove="handleTouchMove"
      @touchstart="handleTouchStart"
      @touchend="handleTouchEnd"
    >
      <view class="slider-button"></view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    width: {
      type: String,
      default: "750",
    },
    height: {
      type: String,
      default: "850",
    },
    beforeImageUrl: {
      type: String,
    },
    afterImageUrl: {
      type: String,
    },
    beforeText: {
      type: String,
      default: "制作前",
    },
    afterText: {
      type: String,
      default: "制作后",
    },
  },

  data() {
    return {
      isPressDown: false, //鼠标是否正按住
      x: this.width / 2, //设置位置
    };
  },
  methods: {
    handleTouchStart(event) {
      this.isPressDown = true;
      this.startX = event.touches[0].clientX; // 记录触摸起始点
      this.sliderStartX = this.x; // 记录slider起始位置
    },
    handleTouchMove(event) {
      if (!this.isPressDown) {
        return;
      }
      const moveX = event.touches[0].clientX - this.startX; // 计算移动距离
      let newX = this.sliderStartX + moveX * 2; // 计算slider新位置
      // 限制 newX 在 0 和 this.width 之间
      newX = Math.max(0, Math.min(newX, this.width));
      this.x = newX; // 更新位置
    },
    handleTouchEnd() {
      this.isPressDown = false;
    },
    previewImage(e) {
	  const staticPrefix = "static";
	  const imageType = e.currentTarget.dataset.type;
	  const imageUrlMap = {
	    before: this.beforeImageUrl,
	    after: this.afterImageUrl,
	  };
	  // 如果当前图片URL中包含静态前缀,则直接返回
	  if (imageUrlMap[imageType].includes(staticPrefix)) {
	    return;
	  }
	  // 获取当前图片的URL,并使用uni.previewImage方法展示图片
	  const currentImageUrl = imageUrlMap[imageType];
	  uni.previewImage({
	    urls: [imageUrlMap.before, imageUrlMap.after],
	    current: currentImageUrl,
	  });
	}
  },
};
</script>

<style lang="scss" scoped>
.img-comparison-container {
  position: relative;
  display: inline-block;
  overflow: hidden;
  border-radius: 20rpx;

  .before-image {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    width: 50%;
    overflow: hidden;

    .before-text {
      position: absolute;
      left: 22rpx;
      top: 22rpx;
      color: #ffffff;
      background: rgba(34, 34, 34, 0.5);
      border-radius: 20rpx;
      padding: 5rpx 15rpx 5rpx 15rpx;
      font-size: 24rpx;
      white-space: nowrap;
    }
  }

  .after-image {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0;

    .after-text {
      position: absolute;
      right: 22rpx;
      top: 22rpx;
      color: #ffffff;
      background: rgba(34, 34, 34, 0.5);
      border-radius: 20rpx;
      padding: 5rpx 15rpx 5rpx 15rpx;
      font-size: 24rpx;
      white-space: nowrap;
    }
  }

  .images {
    width: 100%;
    height: 100%;
  }

  .slider-bar {
    cursor: move;
    position: absolute;
    width: 4rpx;
    left: 50%;
    top: 0rpx;
    background: #ffffff;
    height: 100%;
    display: block;
    z-index: 2;
    box-shadow: 0 0 20rpx 1px rgba(0, 0, 0, 0.4);

    .slider-button {
      position: absolute;
      width: 60rpx;
      height: 60rpx;
      border-radius: 50%;
      border: 4rpx solid #ffffff;
      background-color: transparent;
      left: calc(50% - 30rpx);
      top: calc(50% - 30rpx);
    }

    &::before {
      content: "";
      padding: 6rpx;
      border: solid #ffffff;
      border-width: 0 4rpx 4rpx 0;
      position: absolute;
      top: calc(50% - 8rpx);
      left: calc(50% - 16rpx);
      transform: rotate(135deg);
      z-index: 1;
    }

    &::after {
      content: "";
      padding: 6rpx;
      border: solid #ffffff;
      border-width: 0 4rpx 4rpx 0;
      position: absolute;
      top: calc(50% - 8rpx);
      left: 50%;
      transform: rotate(-45deg);
    }
  }
}
</style>

使用方法

引入组件

import compareImage from "../components/index.vue";
<compare-image
  :beforeImageUrl="image.beforeImg"
  :afterImageUrl="image.afterImg"
  width="624"
  height="624"
  beforeText="修复前"
  afterText="修复后"
/>

在这里插入图片描述
感谢你的阅读,如对你有帮助请收藏+关注!
只分享干货实战精品从不啰嗦!!!
如某处不对请留言评论,欢迎指正~
博主可收徒、常玩QQ飞车,可一起来玩玩鸭~

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cnsv雨

谢谢您的鼓励,我会继续努力的~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值