微信小程序movable view移动图片和双指缩放实例代码

movable-area是微信小程序的新组件,可以用来移动视图区域movable-view。移动方向可选择任何、垂直和平行。可移动区域里包含其他文本、图片、按钮等组件。可移动区域可绑定touchend等事件。movable-view的参数可调整动画效果。

先从movable-view开始说起吧. movable-view是小程序自定义的组件.其描述为:"可移动的视图容器,在页面中可以拖拽滑动". 官方文档地址:

https://mp.weixin.qq.com/debug/wxadoc/dev/component/movable-view.html.

值得注意的是文档中有一段备注: "当movable-view小于movable-area时,movable-view的移动范围是在movable-area内;当movable-view大于movable-area时,movable-view的移动范围必须包含movable-area(x轴方向和y轴方向分开考虑)". 也就是说父容器movable-area是可以比子容器movable-view小的,但是子容器的移动范围必须包括父容器.

先看官方实例代码:

<view class="section">
 <view class="section__title">movable-view区域小于movable-area</view>
 <movable-area style="height: 200px;width: 200px;background: red;">
 <movable-view style="height: 50px; width: 50px; background: blue;" x="{{x}}" y="{{y}}" direction="all">
 </movable-view>
 </movable-area>
 <view class="btn-area">
 <button size="mini" bindtap="tap">click me to move to (30px, 30px)</button>
 </view>
 <view class="section__title">movable-view区域大于movable-area</view>
 <movable-area style="height: 100px;width: 100px;background: red;" direction="all">
 <movable-view style="height: 200px; width: 200px; background: blue;">
 </movable-view>
 </movable-area>
</view>

这里面有个错误,应该是编写人的一点小失误吧. 第二个movable-area的属性direction应该写在movable-view上.

 <movable-area style="height: 100px;width: 100px;background: red;" >
  <movable-view style="height: 200px; width: 200px; background: blue;" direction="all">
  </movable-view>
 </movable-area>

看下效果:

1) 当movable-view区域小于movable-area时,子容器movable-view只能在父容器内移动.  下图的效果是设置了属性 out-of-bounds="true"的效果. out-of-bounds可以染子容器到达父容器边界时有个超出边界然后回弹的动画. 并不是真正能让子容器移动到父容器以外.

2) 当movable-view区域大于movable-area时,子容器移动的范围必须包括父容器.

 

第二种情况中,把父容器看做手机屏幕可视区域,子容器看做要查看的长图,大图. 就可以实现拖动查看图片的效果. 如果图片时动态加载的,不是固定的图片,就要兼容图片宽高小于屏幕可视宽高和图片宽高大于可视屏幕宽高的可能性,也就是要考虑到以上两种情况.

我们要在movable组件加载的同时设置好movable-view的宽高,因为movable组件加载成功后再去改变movable-view的大小,可移动区域是不会变的. 我们可以通过页面中要查看的图片的onload事件中获取图片宽高(目前我只发现bindload事件能获取到图片宽高),然后存储起来imgWidth和imgHeight. 当用户点击图片时,在bindtap事件中设置好movable-view的宽高,同时将movable-area的弹窗wx;if设置为true.

 <!-- 要查看的图片列表 -->
   <view class="flex-wrap flex-pic">
     <view class="picList">
     <image wx:for="{{item.imglist}}" wx:for-item="itemImg" wx:key="*this" id="{{'rfnd_'+index}}" bindload="imageOnload" src="{{ itemImg}}" bindtap="showResizeModal" data-src="{{itemImg}}"></image>
    </view>
   </view>

因为要查看的是一个图片列表, 我用了一个数组去存储每个图片的宽高,然后通过图片id来关联

/**
 * 加载图片
 */
 imageOnload:function(e){
 var id = e.currentTarget.id
 this.data.imgIdList[id] = {
  width:e.detail.width,
  height:e.detail.height
 }
 },
 模板页面
<!--components/resizePicModal/resizePicModal.wxml-->
<template name="resizePic">
 <scroll-view class="backdrop">
 <view class="close-icon" bindtap="closeResizeModal">
  取消预览
 </view>
 <movable-area style="width:100%;height:100%;" >
  <movable-view direction="all"
  out-of-bounds="true" x="{{img.x}}" y="{{img.y}}" >
  <image mode="widthFix" class="dtl-img" src="{{img.currentSrc}}"></image>
  </movable-view>
 </movable-area>
 </scroll-view>
 </template>
 /**
 * 打开弹窗
 */
 showResizeModal: function (e) {
 var src = e.currentTarget.dataset.src;
 var x = 0
 var y =0
 try {
  var width = this.imgIdList[e.currentTarget.id].width; //图片原宽
  var height = this.imgIdList[e.currentTarget.id].height; //图片原高

  //小程序默认固定宽320px,获取top和left值,使图片居中显示
  height = height * (320 / width);
  width = 320;
    
  x = (app.windowWidth - width) / 2
  y = (app.windowHeight - height) / 2

 } catch (e) { }
 var img = {
  x: x,
  y: y,26  currentSrc: src,
 };
 this.setData({ img: img, isCheckDtl: true });

 },

部分CSS代码

.backdrop{
 background: rgba(0, 0, 0, 1);
 width:100%;
 height: 100%;
 position: fixed;
 top:0;
 left:0;
}

以上基本上可以完成一个点击查看图片的需求.

然而如果再支持双指缩放的话,movable-view实现不了.我暂没想出来怎么实现,如果有人知道,希望能够指点迷津. 主要原因是因为还是我上文提到的那句话:"movable组件加载成功后再去改变movable-view的大小,可移动区域是不会变的".缩放后图片大小肯定会改变的. 缩小还好,一旦放大,可移动区域还是原来的不会改变.想象一下,如果一张宽度刚刚好时屏幕可视宽度的图片,放大后,这张图片就只能在屏幕可视宽度windowWidth的范围中移动,看不到左也看不到右边超出的部分.

所以如果既要可移动图片又要可缩放,就不能用movable-view组件了,自己写个吧. 原来bindtouchmove会触发页面的滚动条,但是现在微信好像已经修复了这个BUG,我今天在真机上测试没有出现这个问题.

自定义控件resizePicModal.wxml:

<!-- 缩放 -->
<template name="resizePic">
 <scroll-view class="backdrop" catchtouchmove="bindTouchMove" catchtouchend="bindTouchEnd" bindtouchstart="bindTouchStart" >
 <view class="close-icon" bindtap="closeResizeModal">
  取消预览
 </view>
  <image catchtouchmove="bindTouchMove" bindtouchend="bindTouchEnd" bindtouchstart="bindTouchStart"
  style=" transform: scale({{img.baseScale}}); position:absolute; top:{{img.top}}px; left:{{img.left}}px; "
  mode="widthFix" class="dtl-img" src="{{img.currentSrc}}"></image>
 </scroll-view>
 </template>

JS: resizePicModal.js

 /**
 * 使用方法:
 * 1) WXHTML要缩放的图片 必须 传入 src 以及绑定 bindtap事件,
 * e.g:
 * <image bindtap="toggleDtl" data-src="{{item}}" wx:for="{{productCard.arrImg}}" wx:key="*this" src="{{item}}" style="width:100%" mode="widthFix"></image>
 * 2) WXHTML 要引入Modal模板(isCheckDtl无需再定义):
 *  <view wx:if="{{isCheckDtl}}">
 *  <import src="/components/resizePicModal/resizePicModal.wxml"/>
 *  <template is="resizePic" data="{{img}}"></template>
 *  </view>
 * 3) JS页面要引入JS文件,覆盖当前页面的事件:
 * var resizePicModalService = require ('../../components/resizePicModal/resizePicModal.js')
 * var resizePicModal = {}
 * 4) 在onLoad事件中,实例化ResizePicModal
 *  resizePicModal = new resizePicModalService.ResizePicModal()
 */
var app = getApp()
let modalEvent = {
 distanceList: [0, 0],//存储缩放时,双指距离.只有两个数据.第一项为old distance.最后一项为new distance
 disPoint: { x: 0, y: 0 },//手指touch图片时,在图片上的位置
 imgIdList:{},
 /**
 * 打开弹窗
 */
 showResizeModal: function (e) {
 var src = e.currentTarget.dataset.src;
 var x = 0
 var y =0
 try {
  var width = this.imgIdList[e.currentTarget.id].width; //图片原宽
  var height = this.imgIdList[e.currentTarget.id].height; //图片原高
  //小程序固定宽320px
  height = height * (320 / width);
  width = 320;
  x = (app.windowWidth - width) / 2 //> 0 ? (app.windowWidth - width) / 2 : 0;
  y = (app.windowHeight - height) / 2// > 0 ? (app.windowHeight - height) / 2 : 0;
 } catch (e) { }
 var img = {
  top: y,
  left: x,
  x: x, y: y,
  width: '100%',
  baseScale: 1,
  currentSrc: src,
 };
 this.setData({ img: img, isCheckDtl: true });
 },
 /**
 * 关闭弹窗
 */
 closeResizeModal:function(){
 this.setData({ isCheckDtl: false })
 },
 /**
 * 加载图片
 */
 imageOnload:function(e){
 var id = e.currentTarget.id
 this.imgIdList[id] = {
  width:e.detail.width,
  height:e.detail.height
 }
 },
 /**
 * bindtouchmove
 */
 bindTouchMove: function (e) {
 if (e.touches.length == 1) {//一指移动当前图片
  this.data.img.left = e.touches[0].clientX - this.disPoint.x
  this.data.img.top = e.touches[0].clientY - this.disPoint.y
  this.setData({ img: this.data.img })
 }
 if (e.touches.length == 2) {//二指缩放
  var xMove = e.touches[1].clientX - e.touches[0].clientX
  var yMove = e.touches[1].clientY - e.touches[0].clientY
  var distance = Math.sqrt(xMove * xMove + yMove * yMove);//开根号
  this.distanceList.shift()
  this.distanceList.push(distance)
  if (this.distanceList[0] == 0) { return }
  var distanceDiff = this.distanceList[1] - this.distanceList[0]//两次touch之间, distance的变化. >0,放大图片.<0 缩小图片
  // 假设缩放scale基数为1: newScale = oldScale + 0.005 * distanceDiff
  var baseScale = this.data.img.baseScale + 0.005 * distanceDiff
  if(baseScale>0){
  this.data.img.baseScale = baseScale
  var imgWidth = baseScale * parseInt(this.data.img.imgWidth)
  var imgHeight = baseScale * parseInt(this.data.img.imgHeight)
  this.setData({ img: this.data.img })
  }else{
  this.data.img.baseScale = 0
  this.setData({ img: this.data.img })
  }
 }
 },
 /**
 * bindtouchend
 */
 bindTouchEnd: function (e) {
 if (e.touches.length == 2) {//二指缩放
  this.setData({ isCheckDtl: true })
 }
 },
 /**
 * bindtouchstart
 */
 bindTouchStart: function (e) {
 this.distanceList = [0, 0]//回复初始值
 this.disPoint = { x: 0, y: 0 }
 if (e.touches.length == 1) {
  this.disPoint.x = e.touches[0].clientX - this.data.img.left
  this.disPoint.y = e.touches[0].clientY - this.data.img.top
 }
 }
}
function ResizePicModal(){
 let pages = getCurrentPages()
 let curPage = pages[pages.length - 1]
 Object.assign(curPage, modalEvent)//覆盖原生页面事件
 this.page = curPage
 curPage.resizePicModal = this
 return this
}
module.exports = {
 ResizePicModal
}

业务页面wxml:引入自定义控件模板

<view class="flex-wrap flex-pic">
    <view class="picList">
     <image wx:for="{{item.imglist}}" wx:for-item="itemImg" wx:key="*this" id="{{'rfnd_'+index}}" bindload="imageOnload" src="{{ itemImg}}" bindtap="showResizeModal" data-src="{{itemImg}}"></image>
    </view>
 </view>
<!-- 缩放 -->
 <view wx:if="{{isCheckDtl}}">
 <import src="/components/resizePicModal/resizePicModal.wxml"/>
 <template is="resizePic" data="{{img}}"></template>
 </view>

业务页面js,引用js文件,实例化resizePicModal

var that
 var resizePicModal = {}
 var app = getApp()
 var resizePicModalService = require('../../components/resizePicModal/resizePicModal.js')
 /**
  * 生命周期函数--监听页面加载
  */
 onLoad: function (options) {
  that = this 8  resizePicModal = new resizePicModalService.ResizePicModal()
 }

总结

以上所述是小编给大家介绍的微信小程序movable view移动图片和双指缩放实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法

    本文实例讲述了JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法.分享给大家供大家参考,具体如下: 为什么会有人会使用ctrl+鼠标滚轮缩放网页?坚决禁止! <html> <head> <title>测试</title> <script language="javascript"> var scrollFunc=function(e){ e=e || window.event; if(e.wheelDelta &&a

  • 自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结

    一.先明白几个概念 phys.width: device-width: 一般我们所指的宽度width即为phys.width,而device-width又称为css-width. 其中我们可以获取phys.width即width通过document.documentElement.clientWidth;而获取css-width通过 window.screen.width获取.如iphone6的phys.width为750px,而css-width为375px. 二.明白一个浏览器默认行为. 试

  • jQuery实现按比例缩放图片的方法

    本文实例讲述了jQuery实现按比例缩放图片的方法.分享给大家供大家参考,具体如下: 做网站的时候,相信有很多朋友都会遇到图片过大,导致页面撑开变形的问题,如果强制设置width,height,图片则会因为强制变形而走样.在这里我介绍一种简单的按比例缩放图片的方法. 对于一堆图片 <img src="1.jpg" border="1"></img> <img src="2.jpg" border="1&qu

  • 学习使用Material Design控件(四)Android实现标题栏自动缩放、放大效果

    本文要实现内容移动时,标题栏自动缩放/放大的效果,效果如下: 控件介绍 这次需要用到得新控件比较多,主要有以下几个: CoordinatorLayout 组织它的子views之间协作的一个Layout,它可以给子View切换提供动画效果. AppBarLayout 可以让包含在其中的控件响应被标记了ScrollingViewBehavior的View的滚动事件 CollapsingToolbarLayout 可以控制包含在CollapsingToolbarLayout其中的控件,在响应colla

  • JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码

    手机的屏幕有大有小,移动web最好做成响应式布局,也就是自适应屏幕,没有固定宽高,这样的话,在所有手机上都可以正常显示.关于移动端页面按手机屏幕分辨率自动缩放的js,先附上代码 <script> var phoneWidth = parseInt(window.screen.width); var phoneHeight = parseInt(window.screen.height); var phoneScale = phoneWidth/750;//除以的值按手机的物理分辨率 var u

  • 关于meta viewport中target-densitydpi属性详解(推荐)

    前段时间在做WAP页面,发现页面设置了meta viewport中的大众属性,即: <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" >  但发现页面依旧不根据手机屏幕进行自动缩放,后来找其他同事帮忙解决了,我看了源代码发现了是在原来的viewport中增加了target-densitydpi属性.看之初不太了解,也因为当时自己手

  • 微信小程序movable view移动图片和双指缩放实例代码

    movable-area是微信小程序的新组件,可以用来移动视图区域movable-view.移动方向可选择任何.垂直和平行.可移动区域里包含其他文本.图片.按钮等组件.可移动区域可绑定touchend等事件.movable-view的参数可调整动画效果. 先从movable-view开始说起吧. movable-view是小程序自定义的组件.其描述为:"可移动的视图容器,在页面中可以拖拽滑动". 官方文档地址: https://mp.weixin.qq.com/debug/wxadoc

  • 微信小程序开发之左右分栏效果的实例代码

    本文以一个简单的小例子,简述在微信小程序开发中左右分栏功能的实现方式,主要涉及scroll-view ,列表数据绑定,及简单样式等内容,属于初级入门内容,仅供学习分享使用. 概述 在微信小程序开发中,左右分栏(左边显示分类,右边显示明细,然后进行联动)是一种常见的布局方式,多应用于点餐,冷饮店,外卖,以及其他类似的商城. 布局分析 布局分析图示如下: 涉及知识点 •scroll-view 可滚动视图区域.使用竖向滚动时,需要给<scroll-view>一个固定高度,通过 WXSS 设置 hei

  • 微信小程序授权登陆及每次检查是否授权实例代码

    授权登录 <button open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo" class="fix">登录</button> //index.js //获取应用实例 var APPID ='xxx' var SECRET = 'xxx' const app = getApp() Page({ data: { list:

  • 微信小程序教程之本地图片上传(leancloud)实例详解

    微信小程序 leancloud --本地图片上传 由于本站最近学习微信小程序的知识,这里记录下微信小程序实现本地上传的功能实现方法,以下是网上找的资料,大家看下. 将本地图片上传至leancloud后台. 获取本地图片或者拍照,我在上一篇博文中写过.这里就不说了.我的博客 直接上代码: 1.index.js //index.js //获取应用实例 var app = getApp() const AV = require('../../utils/av-weapp.js'); Page({ da

  • 微信小程序 五星评分(包括半颗星评分)实例代码

    微信小程序 五星评分 一位同学说要写五星评分.要有半颗星的评分. 于是我做了个玩具.有空了做模块化,这代码看不下去了. 代码: 1.index.wxml <!--index.wxml--> <block wx:for="{{stars}}"> <image class="star-image" style="left: {{item*150}}rpx" src="{{key > item ?(key-

  • 微信小程序 视图容器组件的详解及实例代码

    微信小程序 视图容器组件详解: 小程序给出的视图容器组件有三个:</view>.</scroll-view>和</swiper>: 1.</view> 视图容器 </view>相当于html中的</div>标签,有四个属性: hover和hover-class与点击效果有关:hover设置是否启用点击效果,而hover-class设置点击的效果. hover-start-time和hover-stay-time与点击效果的时间有关:h

  • 微信小程序 滚动选择器(时间日期)详解及实例代码

    微信小程序  滚动选择器(时间日期)详解 微信小程序自己封装了很多控件,用起来确实很方便,如果这是Android里面,还需要自己去定义,不废话,效果图: 一起来看看怎么实现的呢?看完你应该就该说,尼玛,这就行啦-. 这个效果呢,要用到picker组件,动画从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器. 看下相应的属性: 具体的来看看代码,布局: <view class="section" > <

  • 微信小程序左右滑动切换页面详解及实例代码

    微信小程序--左右滑动切换页面事件 微信小程序的左右滑动触屏事件,主要有三个事件:touchstart,touchmove,touchend. 这三个事件最重要的属性是pageX和pageY,表示X,Y坐标. touchstart在触摸开始时触发事件; touchend在触摸结束时触发事件; touchmove触摸的过程中不断激发这个事件; 这三个事件都有一个timeStamp的属性,查看timeStamp属性,可以看到顺序是touchstart => touchmove=> touchmov

  • 微信小程序有旋转动画效果的音乐组件实例代码

    在微信开发中,写过的一个简单的音乐播放组件,记录下. music 音乐播放组件. 属性 属性名 类型 默认值 说明 music String   传入的音乐资源地址 musicStyle String (随便写了个) 音乐组件的样式 rotate Boolean true 播放时是否有旋转效果 iconOn String (随便写了个) 音乐播放时的icon地址 iconOff String (随便写了个) 音乐暂停时的icon地址 代码 properties: { // 音乐路径 music:

  • 微信小程序  滚动选择器(时间日期)详解及实例代码

    微信小程序  滚动选择器(时间日期)详解 微信小程序自己封装了很多控件,用起来确实很方便,如果这是Android里面,还需要自己去定义,不废话,效果图: 一起来看看怎么实现的呢?看完你应该就该说,尼玛,这就行啦-. 这个效果呢,要用到picker组件,动画从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器. 看下相应的属性: 具体的来看看代码,布局: <view class="section" > <

随机推荐