cover_image

微信小程序中实现手势缩放图片

technote小程序微信教程手势缩放
yh

<p><img class="aligncenter size-full wp-image-740761" src="http://ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/feature-1.jpg" alt="feature-1" width="1000" height="625" srcset="http://www.ifanr.com/wp-content/uploads/2016/11/feature-1.jpg 1000w, http://www.ifanr.com/wp-content/uploads/2016/11/feature-1-360x225.jpg 360w, http://www.ifanr.com/wp-content/uploads/2016/11/feature-1-768x480.jpg 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></p> <p>在开发「知了地铁」小程序的时候,我们发现:在几寸的手机屏幕上完整显示地铁线网图,用户就很难看清细节;而默认将线网图按照 1:1 模式显示出来,用户需要多次拖动才能看到线网图的概况。</p> <p>很明显,两种实现方式的体验,都非常糟糕。</p> <p><img class="aligncenter size-full wp-image-755071" src="http://ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/scale-1.jpg" alt="scale-1" width="1000" height="1338" srcset="http://www.ifanr.com/wp-content/uploads/2016/11/scale-1.jpg 1000w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-1-360x482.jpg 360w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-1-768x1028.jpg 768w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-1-765x1024.jpg 765w" sizes="(max-width: 1000px) 100vw, 1000px" /></p> <p>因此,如果要在小程序中展示带有细节信息的图片(例如地铁线网图),就需要为其加上缩放功能。而用双指张合手势进行缩放,是大部分智能手机用户都已经习惯了的缩放方法。</p> <p>今天,知晓程序就为大家带来有关手势缩放功能的实现方法,以及手势缩放实现在小程序中的局限和问题。</p> <p><span style="color: gray; font-size: 14px;">关注知晓程序(微信号 zxcx0101),回复「<span style="color: #605eac;">知了地铁</span>」,抢先看「知了地铁」小程序上手体验文章。</span></p> <h3><span style="color: #605eac;">手势动态检测</span></h3> <p>首先,我们需要获得用户的触摸事件。只有获得了这个事件,小程序才能得知用户希望缩放图片,同时确定图片的缩放倍数。</p> <p>我们发现微信提供 touchmove 事件,在用户触摸屏幕并在屏幕上移动手指时,这个事件就会被触发。</p> <p>手势缩放的核心思想是:根据两只手指相对距离的变化来对图片进行放大或缩小。因此,我们需要知道两只手指相对距离的变化,才能做到良好的缩放体验。</p> <p><code>touchmove</code> 事件可以实现的功能,大致可以总结为:</p> <ul> <li>手指在屏幕上进行移动时,对应的组件上就会以 16 ms 一次的频率不断触发 <code>touchmove</code> 事件;</li> <li>手指离开屏幕后,则会触发 <code>touchend</code> 事件。</li> </ul> <p><code>touchmove</code> 事件所包含的事件对象中有一个 <code>touches</code> 属性,此属性为当前停留在屏幕中的触摸点信息的数组。触摸点的信息包括:</p> <ul> <li><code>identifier</code>:触摸点的标志符;</li> <li><code>pageX</code> 和 <code>pageY</code>:距离文档左上角的距离;</li> <li><code>clientX</code> 和 <code>clientY</code>:距离屏幕可显示区域左上角距离。</li> </ul> <p>我们可以通过不断获取 <code>clientX</code> 和 <code>clientY</code> 数据的方式,来确定手指在屏幕上的位置变化。</p> <pre><code>xMove = e.touches[1].clientX - e.touches[0].clientX; yMove = e.touches[1].clientY - e.touches[0].clientY; distance = Math.sqrt(xMove * xMove + yMove * yMove);</code></pre> <p><code>distance</code> 变量即为两只手指之间的距离。在 <code>touchmove</code> 被触发的时候,小程序就会计算一次 <code>distance</code>。</p> <p>我们为新的 <code>distance</code> 变量定名为 <code>newDistance</code>,相应地,旧变量定名为 <code>oldDistance</code>。</p> <p>之后,我们设定一个新的变量 <code>distanceDiff = newDistance - oldDistance</code>,它反映两次 <code>touchmove</code> 触发瞬间,两根手指相对距离的变化值。</p> <p><code>distanceDiff</code> 为正数时,表示两指间距离在变大,图片需要被放大;反之,则代表两指间距缩小,图片需要被缩小。</p> <h3><span style="color: #605eac;">图片动态缩放</span></h3> <p>到这里,我们已经可以探测用户的手指距离变化了。接下来,我们需要根据用户的手势,确定图片缩放倍数,然后根据倍数缩放图片。</p> <p>首先,要确定 <code>distance</code> 的变化值与图片放大或缩小的变化率相关联的规则。</p> <p>我们将图片正常显示时的尺寸定为基准值,存放于变量 <code>baseWidth</code> 和 <code>baseHeight</code> 中。图片需要放大的倍数设置为变量 <code>scale</code>,它的初始值和最小值为 <code>1</code>,最大值可根据需要来设置。</p> <p>经过多次试验,我们最后确定了一个公式:</p> <pre><code>newScale = oldScale + 0.005 * distanceDiff</code></pre> <p>此公式中的 <code>0.005</code> 为图片的缩放比例。在实测中,使用 0.005 这个值可获得比较良好的缩放体验。</p> <p>现在,我们为图片对象绑定 <code>touchmove</code> 事件。在每次 <code>touchmove</code> 被触发后,我们都可以计算出新的图片需要被放大的倍数,我们将这个变量定名为 <code>scale</code>。</p> <p>具体方式是:在每次 <code>touchmove</code> 被触发后,通过探测手指距离变化而得到的数据,来得到图片按比例缩放后的高宽值。</p> <pre><code>scaleWidth = scale * baseWidth; scaleHeight = scale * baseHeight;</code></pre> <p>接下来,我们在 WXML 中,将图片对象的高和宽绑定相应的动态值,我们就能实现手势缩放功能了:</p> <pre><code>&lt;image class = "image" src = "..." style = "width:{{ scaleWidth }}px; height:{{ scaleHeight }}px"&gt;</code></pre> <p><img class="aligncenter size-full wp-image-755108" src="http://ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/scale-2.jpg" alt="scale-2" width="1000" height="1338" srcset="http://www.ifanr.com/wp-content/uploads/2016/11/scale-2.jpg 1000w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-2-360x482.jpg 360w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-2-768x1028.jpg 768w, http://www.ifanr.com/wp-content/uploads/2016/11/scale-2-765x1024.jpg 765w" sizes="(max-width: 1000px) 100vw, 1000px" /></p> <h3><span style="color: #605eac;">用 <code>scroll-view</code>,还是用 <code>view</code>?</span></h3> <p>实现了图片的缩放之后,还需要一个容器存放图片。微信为视图组件提供了 `scroll-view` 和 `view` 两种容器容。但在目前阶段,两种容器都不能非常完美地实现手势缩放功能。</p> <p>我们原本使用的方案是:利用 <code></code><code>scroll-view</code>,设置 <code>scroll-x</code> 和 <code>scroll-y</code> 属性为 <code>true</code>。这样做,可以在放大并滑动浏览图片时,拥有良好的浏览体验。</p> <p>但是,我们发现 <code>scroll-view</code> 组件还存在缩放时出现界面闪动的现象的 bug。用双指手势缩放存在 <code>scroll-view</code> 容器中的图片,极易触发此 bug。</p> <p>此问题只能等待微信官方进行修复。但在目前阶段,开发者也可以选择:</p> <ul> <li>放弃 <code>scroll-view</code>,转而使用不带有良好滑动体验的 view 组件;</li> <li>放弃使用手势缩放功能,转而开发「放大 &#8211; 缩小」按钮组件。</li> </ul> <p>以上就是知晓程序(微信号 zxcx0101)带来的手势缩放图片功能的实现教程。虽然目前手势缩放并不能完美实现,但也希望大家可以举一反三,通过这个思路,创造出体验更好的小程序。</p> <p><strong>本文由知晓程序原创出品,关注微信号 zxcx0101,回复「<span style="color: #605eac;">上手</span>」获取全网最值得看的小程序上手体验系列文章。</strong></p> <p style="text-align: center;"><span style="color: #605eac;">快速关注知晓程序↓↓↓</span></p> <p><img class="aligncenter wp-image-743320 size-full" src="http://images.ifanr.cn/wp-content/uploads/2016/11/zxcx-1.jpg" sizes="(max-width: 960px) 100vw, 960px" srcset="//ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/zxcx-1.jpg 960w, //ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/zxcx-1-360x203.jpg 360w, //ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/11/zxcx-1-768x432.jpg 768w" alt="zxcx" width="960" height="540" /><strong><span style="color: #605eac;">知晓程序<span class="s1">(</span>微信号<span class="s1"> zxcx0101)</span></span>是爱范儿旗下专注于小程序生态的公众号。我们提供最全面、新鲜的小程序资讯<span class="s1">(</span>消息、观点、指南、活动<span class="s1">)</span>和服务<span class="s1">,在这里你</span>能了解到关于小程序的一切。</strong></p>