js 移动端 图片放大预览+拖拽

该代码示例展示了如何在Vue.js应用中创建一个半成品的图片预览功能,支持单指拖动和双指放大缩小。虽然没有做完整的边界判断,但解决了放大时图像失真的问题。用户可以点击图片开启预览模式,然后通过手势进行拖动和缩放操作。

只做了放大预览和拖拽,拖拽没有做边界判断,代码可以直接拿去用。

用了其他插件放大都会出现失真的问题,于是直接手写了个半成品,优化没有做。

<template>
  <view class="notFound" style="position: relative;">
    <view class="notFoundBox">
      <view class="img">
        <img
          src="/prod/default/20230107/XEHz9bZVE3SJbTgthy.jpg"
          @click="isshow = true"
          style="width: 100%"
        />
      </view>
    </view>

    <view
      style="
        height: 100%;
        width: 100%;
        position: absolute;
        left:0;
        top:0;
        background: rgba(0, 0, 0, 0.8);
        overflow:hidden;
      "
      
      v-show="isshow"
      @click.stop="closeImg"
      @touchstart="gtouchstart"
      @touchmove="gtouchmove"
      @touchend="gtouchend"
    >
      <view class="img" style="margin-top: 50%;position: relative;"
       >
        <img 
        class="setImg"
        style="position: absolute; width:52vh;"
        :src="imgPath" 
        :style="{ left: L + 'px', top: T + 'px' ,}" 
        />
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      //图片单指拖动
      L:0,
      T:0,
      //边界判断
      windowW:0,
      windowH:0,
      //双指判断放大缩小
      start: {
        pageX: null,
        pageY: null,
      },
      //双指首次操作未结束并连续进行放大缩小操作
      start2: {
        pageX: null,
        pageY: null,
      },
      //
      distance:null,
      //放大倍数
      swipeScale:1,
      //双指操作是否结束
      once:false,
      //打卡图片预览
      isshow: false,
      imgPath: "/prod/default/20230107/XEHz9bZVE3SJbTgthy.jpg",
    };
  },
  onLoad(){
    let that = this
    uni.getSystemInfo({//可以用来做边界判断
      success: function(res){
        console.log(res)
        that.windowW = res.windowWidth 
        that.windowH = res.windowHeight
      }
    })
  },
  mounted(){
    //获取dom元素用于后期操作
    this.img = document.getElementsByClassName('setImg')[0]
  },
  methods: {
    gtouchstart(e) {
      if(e.touches.length>1){//双手势
        let point1 = e.touches[0];
        let point2 = e.touches[1];
        let deltaX = Math.abs(point2.pageX - point1.pageX);
        let deltaY = Math.abs(point2.pageY - point1.pageY);
        this.distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);//初始时候的距离,r1
    }else{
    //单手势事件
        this.start.pageX = e.touches[0].pageX;
        this.start.pageY = e.touches[0].pageY;
        this.start2.pageX = e.touches[0].pageX;
        this.start2.pageY = e.touches[0].pageY;
    }
    },
    gtouchmove(e) {
      if(e.touches.length>1){
        let point1 = e.touches[0];
        let point2 = e.touches[1];
        let deltaX = Math.abs(point2.pageX - point1.pageX);
        let deltaY = Math.abs(point2.pageY - point1.pageY);
        let distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);//1
        if(this.distance){
            let size = distance/this.distance;
            // size大于1 放大手势
            // size小于1 缩小手势
            if(size > 1){
              this.swipeScale += 0.05
            }else{
              //swipeScale 小于等于1 设置minSize(最小缩放值)
              if(this.swipeScale <= 1 ){
                this.swipeScale = 1
                this.L = 0
                this.T = 0
              }else{
                this.swipeScale -= 0.05
              }
            }
            //执行缩放事件
            this.img.style.transform = "scale("+this.swipeScale +")";
        }
        
    }else{
      //单手势事件
        let deltaX  = e.touches[0].pageX - this.start.pageX;
        let deltaY = e.touches[0].pageY- this.start.pageY;
        if(this.once){//判断是否连续放大缩小
          if(deltaX<0 && deltaX>this.start2.pageX){
            this.L += (1.5*this.swipeScale)
          }else if(deltaX > 0 && deltaX>this.start2.pageX){//2 3
            this.L += (1.5*this.swipeScale)
          }

          if(deltaX<0 && deltaX<this.start2.pageX){
            this.L -= (1.5*this.swipeScale)
          }else if(deltaX > 0 && deltaX<this.start2.pageX){//2 3
            this.L -= (1.5*this.swipeScale)
          }

          if(deltaY<0 && deltaY>this.start2.pageY){
            this.T += (1.5*this.swipeScale)
          }else if(deltaY > 0 && deltaY>this.start2.pageY){//2 3
            this.T += (1.5*this.swipeScale)
          }

          if(deltaY<0 && deltaY<this.start2.pageY){
            this.T -= (1.5*this.swipeScale)
          }else if(deltaY > 0 && deltaY<this.start2.pageY){//2 3
            this.T -= (1.5*this.swipeScale)
          }
        }else{
          this.once = true
          if(deltaX >0){
            this.L += (1.5*this.swipeScale)
          }else if(deltaX < 0){
            this.L -= (1.5*this.swipeScale)
          }

          if(deltaY >0){
            this.T += (1.5*this.swipeScale)
          }else if(deltaY < 0){
            this.T -= (1.5*this.swipeScale)
          }
        }
        //存储n-1的位置,用于判断连续放大缩小操作
        this.start2.pageX  = deltaX;
        this.start2.pageY  = deltaY;

    }
     
    },
    gtouchend(e) {
      //手势结束清除无用值
      this.once = false
      this.start = {
        pageX: null,
        pageY: null,
      };
      this.start2 = {
        pageX: null,
        pageY: null,
      };
    },
    preImg() {
      this.isshow = true;
    },
    closeImg(){
      //关闭预览img重置判断值
      this.swipeScale = 1
      this.img.style.transform = "scale("+this.swipeScale +")";
      this.isshow = false;
      this.L = 0
      this.T = 0
    }
  },
};
</script>

<style lang="scss" scoped>
.notFound {
  position: relative;
  height: 100vh;
  background: white;
  .notFoundBox {
    position: absolute;
    top: 30%;
    width: 100%;
    text-align: center;
    .img {
      width: 100%;
    }
    .title {
      font-weight: bold;
      font-size: 36rpx;
      color: #666666;
      margin: 48rpx 0;
      view {
        font-size: 26rpx;
        font-family: PingFang SC;
        font-weight: 500;
        color: #999999;
      }
    }
    .back {
      width: 250rpx;
      height: 72rpx;
      color: white;
      text-align: center;
      border-radius: 72rpx;
      background-color: #286043;
      margin: 0 auto;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值