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>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现移动端图片预览,可以使用一些现成的库,例如PhotoSwipe、viewer.js等,也可以自己实现。 以下是一个简单的实现步骤: 1. 首先,需要监听图片的点击事件,当图片被点击时,显示预览框,并在预览框中显示图片。 2. 接下来,需要实现手势缩放和手势拖动。可以借助Hammer.js等手势库来实现,当用户在图片上进行缩放或拖动时,修改图片的样式,实现缩放和拖动效果。 3. 双击放大功能可以通过监听双击事件来实现,当用户双击图片时,将图片放大到一定的比例。 4. 最后,需要注意一些细节问题,例如在缩放时限制最大最小缩放比例,避免图片过小或过大,同时在预览框中显示图片时,需要对图片进行居中处理,以保证用户体验。 下面是一个简单的示例代码: ```html <!-- HTML部分 --> <div class="preview-container"> <img src="your-image-url" class="preview-image"> </div> ``` ```css /* CSS部分 */ .preview-container { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.8); display: none; justify-content: center; align-items: center; } .preview-image { max-width: 100%; max-height: 100%; } ``` ```javascript // JavaScript部分 var previewContainer = document.querySelector('.preview-container'); var previewImage = document.querySelector('.preview-image'); // 监听图片点击事件 previewImage.addEventListener('click', function() { previewContainer.style.display = 'flex'; }); // 初始化手势库 var mc = new Hammer.Manager(previewImage); mc.add(new Hammer.Pinch()); mc.add(new Hammer.Pan({ threshold: 0 })); var scale = 1, lastScale = 1; var posX = 0, posY = 0, lastPosX = 0, lastPosY = 0; // 监听手势事件 mc.on('pinchstart', function(e) { lastScale = scale; }); mc.on('pinchmove', function(e) { scale = Math.max(1, Math.min(lastScale * e.scale, 3)); previewImage.style.transform = 'scale(' + scale + ') translate(' + posX + 'px,' + posY + 'px)'; }); mc.on('pinchend', function(e) { lastScale = scale; }); mc.on('panstart', function(e) { lastPosX = posX; lastPosY = posY; }); mc.on('panmove', function(e) { posX = lastPosX + e.deltaX; posY = lastPosY + e.deltaY; previewImage.style.transform = 'scale(' + scale + ') translate(' + posX + 'px,' + posY + 'px)'; }); // 监听双击事件 previewImage.addEventListener('dblclick', function() { if (scale === 1) { scale = 2; previewImage.style.transform = 'scale(' + scale + ') translate(' + posX + 'px,' + posY + 'px)'; } else { scale = 1; posX = 0; posY = 0; previewImage.style.transform = 'scale(' + scale + ') translate(' + posX + 'px,' + posY + 'px)'; } }); // 点击预览框关闭预览 previewContainer.addEventListener('click', function() { previewContainer.style.display = 'none'; scale = 1; posX = 0; posY = 0; previewImage.style.transform = 'scale(' + scale + ') translate(' + posX + 'px,' + posY + 'px)'; }); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值