Home  >  Article  >  WeChat Applet  >  Detailed explanation of examples of movable-view moving pictures and two-finger zoom in WeChat mini program

Detailed explanation of examples of movable-view moving pictures and two-finger zoom in WeChat mini program

黄舟
黄舟Original
2017-09-12 11:29:155183browse

movable-area is a new component of WeChat applet, which can be used to move the view area movable-view. This article mainly introduces the WeChat applet movable view moving pictures and two-finger zoom example code. Friends who need it can refer to

movable-area is a new component of the WeChat applet, which can be used to move the view area movable -view. The movement direction can be selected from any, vertical and parallel. The movable area contains other text, pictures, buttons and other components. The movable area can be bound to touchend and other events. The parameters of movable-view can adjust the animation effect.

Let’s start with movable-view. movable-view is a custom component of the mini program. Its description is: "A movable view container that can be dragged and slid on the page."

It is worth noting that there is a note in the document: "When movable-view is smaller than movable-area, the moving range of movable-view is within movable-area; when movable-view is larger than movable-area, movable-view The movement range must include the movable-area (the x-axis direction and the y-axis direction are considered separately). In other words, the parent container movable-area can be smaller than the sub-container movable-view, but the movement range of the sub-container must include the parent container .

Let’s look at the official example code first:


<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>

There is an error here, it should be a small mistake by the writer. Secondly The attribute direction of a movable-area should be written on the 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>

Look at the effect:

1) When the movable-view area is smaller than the movable -area, the child container movable-view can only move within the parent container. The effect in the figure below is the effect of setting the attribute out-of-bounds="true". out-of-bounds can affect the child container when it reaches the boundary of the parent container There is an animation that exceeds the boundary and then rebounds. It does not really allow the child container to move outside the parent container.

2) When the movable-view area is larger than the movable-area, the range of movement of the child container must include the parent container Container.      

                                                                                                      since The area and sub-container are regarded as long or large pictures to be viewed. The effect of dragging and viewing the picture can be achieved. If the picture is loaded dynamically and is not a fixed picture, it must be compatible with the width and height of the picture being smaller than the visible width and height of the screen. The possibility that the width and height of the picture is greater than the width and height of the visible screen must be taken into consideration.

We need to set the width and height of the movable-view while the movable component is loading, because the movable component is loaded After success, change the size of the movable-view, and the movable area will not change. We can get the image width and height through the onload event of the image to be viewed on the page (currently I only found that the bindload event can get the image width and height ), and then store imgWidth and imgHeight. When the user clicks on the image, set the width and height of the movable-view in the bindtap event, and set the pop-up wx;if of the movable-area to true.

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

Because what I want to view is a list of pictures, I used an array to store the width and height of each picture, and then related it through the picture 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 });
 
 },

Part of the CSS code

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

The above can basically complete the requirement of clicking to view the picture.

However, if two-finger zoom is supported, movable-view cannot be implemented. I haven't figured out how to implement it yet. If anyone knows, I hope you can give me some advice. The main reason is because of the sentence I mentioned above: "Change movable-view after the movable component is loaded successfully." The size of the picture, the movable area will not change." The size of the picture will definitely change after zooming. It's okay to zoom out, but once it is zoomed in, the movable area will not change. Imagine if the screen width is just right For a picture with a visible width, after it is enlarged, the picture can only be moved within the range of the windowWidth, the visible width of the screen, and you cannot see the left or right part beyond it.

So if you want it to be movable If the picture needs to be scalable, you can't use the movable-view component. Write it yourself. It turns out that bindtouchmove will trigger the scroll bar of the page, but now WeChat seems to have fixed this bug. I tested it on a real machine today and this problem did not occur.

Custom control 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" 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 (&#39;../../components/resizePicModal/resizePicModal.js&#39;)
 * 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: &#39;100%&#39;,
  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
}

Business page wxml: Introduce custom control template


<view class="flex-wrap flex-pic">
    <view class="picList">   
     <image wx:for="{{item.imglist}}" wx:for-item="itemImg" wx:key="*this" id="{{&#39;rfnd_&#39;+index}}" bindload="imageOnload" src="{{ itemImg}}" bindtap="showResizeModal" 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(&#39;../../components/resizePicModal/resizePicModal.js&#39;)
 /**
  * 生命周期函数--监听页面加载
  */
 onLoad: function (options) {
  that = this 8  resizePicModal = new resizePicModalService.ResizePicModal()
 }

总结

The above is the detailed content of Detailed explanation of examples of movable-view moving pictures and two-finger zoom in WeChat mini program. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn