小程序通过计算两手指之间距离实现图片预览缩放移动

这篇具有很好参考价值的文章主要介绍了小程序通过计算两手指之间距离实现图片预览缩放移动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实现思路:
通过修改imageView的margin-left和margin-top来改变图片的位置以实现图片的单指移动效果和所有操作结束松手后的回弹效果。修改imageView的宽和高以实现图片放大缩小的效果,且需要同时修改其margin-left和margin-top使图片能以【两手指的中间点为原点】缩放。

二、实现
用到margin来改变图片的位置,给imageView设置样式的时候就不是单单写个AspectFit,需要计算出图片为了展示出AspectFit的效果所需的宽高和margin。

三、示例代码
xml代码:

<view class="container">
  <image class="img" src="/assets/images/longpress-image-scan/wx-qr-code.jpg" data-src="/assets/images/longpress-image-scan/wx-qr-code.jpg" bind:tap="previewImage" mode="widthFix" />
  <view class="large-pic" wx:if="{{isPreview}}">
    <scroll-view scroll-y="true" scroll-x="true" class = "imageScroll" style="width:{{img_view_width}}px;height:{{img_view_height}}px" bind:tap="_imgClose">
      <image src="{{recogImg}}" class="img" mode="aspectFit" 
          catchload="_imgLoadEvent"
          catchtouchstart='_touchStartEvent'
          catchtouchmove='_touchMoveEvent'
          catchtouchend='_touchEndEvent'
          catchtouchcancel='_touchEndEvent'  
          style="width: {{ imgWidth }}px;height: {{ imgHeight }}px;margin-top:{{marginTop}}px;margin-left:{{marginLeft}}px;"></image>
    </scroll-view>
  </view>
</view>

js代码:

var lastTouchPoint = { x: 0, y: 0 };
var newDist = 0;
var oldDist = 0;
Page({
  /**
   * 页面的初始数据
   */
  data: {
    isPreview: false,
    rpxR: "",
    img_view_width: "",//scrollview的宽
    img_view_height: "",//scrollview的高
    marginTop: 0,//图片aspectFit显示时顶部的间距
    marginLeft: 0,//图片aspectFit显示时左边的间距
    srcMarginTop: 0,//图片未被缩放时顶部的间距
    srcMarginLeft: 0,//图片未被缩放时左边的间距
    srcWidth: 0,//图片未被缩放时的高
    srcHeight: 0,//图片未被缩放时的宽
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    //根据传入的值设置title
    wx.setNavigationBarTitle({
      title: "图片缩放"
    })
    //给标题和按钮文字赋值
    this.setData({
      rpxR: getApp().globalData.rpxR,
    })
  },
  /** 预览图片 */
  previewImage(e){
    const {src} = e.currentTarget.dataset
    this.setData({
      isPreview: true,
      exampleImageName: src
    })
    this.setData({
      recogImg: this.data.exampleImageName
    })
  /**
   * 这里计算图片以AspectFill方式填充所需的宽、高、margin-left、margin-top数值
   */
    wx.getImageInfo({
      src: this.data.exampleImageName,
      complete: (res) => {
        console.log(res);
        let imageWidth = res.width;
        let imageHeight = res.height;
        let scrollWidth = getApp().globalData.clientWidth;
        let scrollHeight = getApp().globalData.clientHeight;
        // let scrollHeight = 430 / this.data.rpxR;
        //图片显示在view中的宽高度
        var scaleWidth = 0;
        var scaleHeight = 0; 
        //计算图片居中显示需要的margin
        var mLeft = 0;
        var mTop = 0;
        if (imageWidth / imageHeight > scrollWidth / scrollHeight) {
          //图片比较宽,宽度填充
          mLeft = 0;
          mTop = (scrollHeight - (scrollWidth / imageWidth) * imageHeight) * 0.5;
          scaleWidth = scrollWidth;
          scaleHeight = imageHeight * (scrollWidth / imageWidth);
        } else {
          //图片比较长,长度填充
          mTop = 0;
          mLeft = (scrollWidth - (scrollHeight / imageHeight) * imageWidth) * 0.5;
          scaleHeight = scrollHeight;
          scaleWidth = imageWidth * (scrollHeight / imageHeight);
        }
        // console.log(mLeft)
        // console.log(mTop)
        this.setData({
          img_view_width: scrollWidth,
          img_view_height: scrollHeight,
          imgWidth: scaleWidth,
          imgHeight: scaleHeight,
          marginLeft: mLeft,
          srcMarginLeft: mLeft,
          marginTop: mTop,
          srcMarginTop: mTop,
          srcWidth: scaleWidth,
          srcHeight: scaleHeight,
        })
      }
    })
  },
  /**
   * 图片加载完成方法
   */
  _imgLoadEvent: function (event) {
    lastTouchPoint = { x: 0, y: 0 };
    
  },
  /**
     * 触摸开始事件
     */
  _touchStartEvent: function () {
    lastTouchPoint = { x: 0, y: 0 }
    oldDist = 0
  },
  /**
   * 手指移动事件
   */
  _touchMoveEvent: function (e) {
    //单指移动事件
    if (e.touches.length == 1) {
      if (lastTouchPoint.x == 0 && lastTouchPoint.y == 0) {
        lastTouchPoint.x = e.touches[0].clientX
        lastTouchPoint.y = e.touches[0].clientY
      } else {
        var xOffset = e.touches[0].clientX - lastTouchPoint.x
        var yOffset = e.touches[0].clientY - lastTouchPoint.y
        this.setData({
          marginTop: this.data.marginTop + yOffset,
          marginLeft: this.data.marginLeft + xOffset,
        })
        lastTouchPoint.x = e.touches[0].clientX
        lastTouchPoint.y = e.touches[0].clientY
      }
      // console.log(this.data.marginTop)
    }
    //双指缩放事件
    if (e.touches.length == 2) {
      if (oldDist == 0) {
        oldDist = this._spacing(e);
      } else {
        newDist = this._spacing(e);
        if (newDist > oldDist + 1) {
          this._zoom(newDist / oldDist, e);
          oldDist = newDist;
        }
        if (newDist < oldDist - 1) {
          this._zoom(newDist / oldDist, e);
          oldDist = newDist;
        }
      }
    }
  },
  /**
   * 触摸事件结束
   */
  _touchEndEvent: function () {
    //开始回弹
    this._reboundAnimation();
  },
  /**
   * 计算x轴上的双指中心点比例
   */
  _calcXRatio: function (event) {
    var xRatio = ((event.touches[0].clientX + event.touches[1].clientX) / 2 - this.data.marginLeft) / this.data.imgWidth
    return xRatio
  },
  /**
   * 计算y轴上的双指中心点比例
   */
  _calcYRatio: function (event) {
    var yRatio = ((event.touches[0].clientY + event.touches[1].clientY) / 2 - this.data.marginTop) / this.data.imgHeight
    return yRatio
  },
  /**
   * 双指缩放
   */
  _zoom: function (f, event) {
    var xRatio = this._calcXRatio(event)
    var yRatio = this._calcYRatio(event)
    if (this.data.imgWidth <= this.data.view_width && f < 1) {
      var ratio = this.data.view_width / this.data.imgWidth
      this.setData({
        imgWidth: this.data.imgWidth * ratio,
        imgHeight: this.data.imgHeight * ratio
      })
      return;
    }
    if (this.data.imgHeight <= this.data.view_height && f < 1) {
      var ratio = this.data.view_height / this.data.imgHeight
      this.setData({
        imgWidth: this.data.imgWidth * ratio,
        imgHeight: this.data.imgHeight * ratio
      })
      return;
    }
    this.setData({
      //此处的ratio为双指中心点在图片的百分比
      marginLeft: this.data.marginLeft + xRatio * this.data.imgWidth * (1 - f),
      marginTop: this.data.marginTop + yRatio * this.data.imgHeight * (1 - f),
      imgWidth: this.data.imgWidth * f,
      imgHeight: this.data.imgHeight * f,
    })
    // console.log(this.data.marginTop)
  },
  /**
   * 计算两指间距
   */
  _spacing: function (event) {
    var x = event.touches[0].clientX - event.touches[1].clientX;
    var y = event.touches[0].clientY - event.touches[1].clientY;
    return Math.sqrt(x * x + y * y);
  },
  /**
   * 边界的回弹动画
   */
  _reboundAnimation: function () {
    if (this.data.imgWidth / this.data.srcWidth < 1) {
      //缩放比例已经小于1了,直接还原
      this.setData({
        marginLeft: this.data.srcMarginLeft,
        marginTop: this.data.srcMarginTop,
        imgWidth: this.data.srcWidth,
        imgHeight: this.data.srcHeight,
      })
      return ;
    }
    
    //图片已铺满宽或高
    if (this.data.imgWidth > this.data.img_view_width && this.data.marginLeft > 0) {
      //图片宽度已铺满scrollViewWidth且被拉至最左边
      this.setData({
        marginLeft: 0
      })
    }
    if (this.data.imgWidth > this.data.img_view_width && (this.data.marginLeft + this.data.imgWidth) < this.data.img_view_width) {
      //图片宽度已铺满scrollViewWidth且被拉至最右边
      this.setData({
        marginLeft: this.data.img_view_width - this.data.imgWidth
      })
    }
    if (this.data.imgHeight > this.data.img_view_height && this.data.marginTop > 0) {
      //图片高度已铺满scrollViewHeight且被拉至最顶部
      this.setData({
        marginTop: 0
      })
    }
    if (this.data.imgHeight > this.data.img_view_height && (this.data.marginTop + this.data.imgHeight) < this.data.img_view_height) {
      //图片高度已铺满scrollViewHeight且被拉至最底部
      this.setData({
        marginTop: this.data.img_view_height - this.data.imgHeight
      })
    }
    //图片未铺满宽或高
    if (this.data.imgHeight <= this.data.img_view_height) {
      //图片高未铺满scrollViewHeight,垂直居中
      this.setData({
        marginTop: (this.data.img_view_height - this.data.imgHeight) * 0.5
      })
    }
    if (this.data.imgWidth <= this.data.img_view_width) {
      //图片宽未铺满scrollViewWidth,水平居中
      this.setData({
        marginLeft: (this.data.img_view_width - this.data.imgWidth) * 0.5
      })
    }
    
  },
  _imgClose(){
    this.setData({isPreview: false})
  }
})

wxss代码:文章来源地址https://www.toymoban.com/news/detail-794832.html

.large-pic{
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #000;
}
.imageScroll {
  width: 100%;
  height: 430rpx;
  position: fixed;
  background-color: #000;
}
.img {
  position: absolute;
  display: block;
  background-color: #000;
  text-align: center;
}

到了这里,关于小程序通过计算两手指之间距离实现图片预览缩放移动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity计算2个物体之间距离 (2个三维向量之间)

        public float GetDistance(Vector3 startPoint, Vector3 endPoint)     {         float distance = (startPoint - endPoint). magnitude ;         return distance;     }     方法2     public double GetDistance(Vector3 startPoint, Vector3 endPoint)     {         double x = System.Math.Abs(endPoint.x - startPoint.x);         double y

    2024年02月08日
    浏览(36)
  • 根据经纬度计算两点之间的距离

    前言 在我们平时使用美团,饿了么等app进行订餐,或者使用猫眼进行订电影票的时候,都有一个距离的排序,表明该家店距离我们当前的位置,这种基于地理位置的服务,统一被称为LBS(Location Based Service),而LBS的实现则是借助于GIS,WC(无线通信)等信息技术来实现。而今

    2024年02月05日
    浏览(71)
  • 微信小程序wx.previewImage实现图片预览

    在微信小程序中, wx.previewImage 函数用于预览图片,可以将一组图片以轮播的方式展示给用户,并支持用户手势操作进行切换。 使用 wx.previewImage 函数需要传入一个参数对象,该对象包含以下属性: current : String,必填,当前显示图片的链接/路径。 urls : Array,必填,需要预览

    2024年02月06日
    浏览(40)
  • 小程序中使用wx.previewImage实现图片预览与缩放

    在小程序文档中我们可以看到wx.previewImage的功能是在新页面中全屏预览图片,预览的过程中用户可以进行保存图片、发送给朋友等操作。但其实还有一个隐藏功能缩放图片,最小为原比例。话不多说,上代码: xml代码: src的路径换成自己的图片路径就可以了,可以是像上面

    2024年01月17日
    浏览(35)
  • 在 Python 中计算两个 GPS 点之间的距离

    计算两个 GPS 点之间的距离是我们可以在 Python 框架内操作的地理和数学练习。 现在让我们看看如何使用 Python 执行此操作。 haversine 公式是用 Python 计算两个 GPS 点之间距离的一种简化方法,但它的计算是基于地球是一个完美球体的假设。 然而,地球并不是一个完美的球体。

    2024年02月07日
    浏览(30)
  • 微信小程序(二)微信小程序选择本地图片显示并预览(实现左右滑动)

    在微信小程序里面实现选择图片然后预览是一个非常普遍的功能,在我们上传图片文件的时候,都会选择本地的图片进行上传,在上传之前会查看一下自己上传的图片是否准确。所以要做到预览图片。 下面就实现一个简单的本地图片显示预览的功能~~ 1、创建页面 这里我直接

    2024年02月03日
    浏览(45)
  • 学习路之PHP--计算2个坐标点之间距离、时间比较

    参考以下代码:

    2024年02月15日
    浏览(33)
  • 根据经纬度计算地球上两点之间的距离——Haversine公式介绍及计算步骤

    目录 摘要 1.半正矢公式(Haversine Formula)介绍 2.半正矢公式应用 3.半正矢公式计算 3.1 主要思路 3.2 计算步骤 3.2.1 平面向量计算方法 3.2.2 空间向量计算方法 写本文的出发点是需要在Qlik中根据经纬度计算地球上两点间的距离。我在社区上搜到了相关公式的分享,这个公式叫做

    2023年04月10日
    浏览(34)
  • 计算线阵相机 到 拍摄产品之间 摆放距离?(隐含条件:保证图像不变形)

    一物体被放置在传送带上,转轴的直径为100mm。已知线阵相机4K7u(一行共4096个像素单元,像素单元大小7um),镜头35mm,编码器2000脉冲/圈。保证图像不变形的条件下,计算相机到产品之间 摆放距离?无论传送带速度变化为多少,都不变形。                  解:编码

    2024年02月08日
    浏览(40)
  • 微信小程序---图片裁剪、旋转、预览、上传功能实现(已经封装成组件,需要的到资源下载)

    1、可以拍摄或选择本地图片上传图片数据 2、图片上传数据可以进行裁剪、选择、取消、裁剪后预览、上传以及限制大小,还可以缩放操作,需要的可以解除限制即可 1、点击图片上传按钮时,跳转页面到cropper进行图片选择剪切 wx.navigateTo({       url: `/pages/cropper/cropper?d

    2023年04月26日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包