【前端】原生实现图片的放大与缩放

avatar
作者
筋斗云
阅读量:0

需求

点击图片,出现一个蒙版和图片,双指捏合可以使图片放大或缩小。

使用前端框架是svelte,但是不影响,功能都是JS实现。

代码

相关定义:

  import { onMount, afterUpdate, onDestroy } from 'svelte';      let imgDetailRef;   let initialDistance = 0;   let initialScale = 1;   let currentScale = 1; 

定义监听事件触发的方法:

scale(${currentScale})是缩放相关的样式。

  const getDistanceBetweenTouches = (ev) => {     let [touch1, touch2] = ev.touches;     return Math.sqrt(       Math.pow(touch1.pageX - touch2.pageX, 2) +         Math.pow(touch1.pageY - touch2.pageY, 2),     );   };      const touchStartHandler = function (ev) {     if (ev.touches.length === 2) {       initialDistance = getDistanceBetweenTouches(ev);       initialScale = currentScale;     }   };    const touchMoveHandler = function (ev) {     // 防止出现Infinity      if (ev.touches.length === 2 && initialDistance !== 0) {       let distance = getDistanceBetweenTouches(ev);       if (distance !== initialDistance) {         currentScale = (initialScale * distance) / initialDistance;         // 最多只能缩小到原本大小         if (currentScale < 1) currentScale = 1;         imgDetailRef.style.transform = `translate(-50%, -50%) scale(${currentScale})`;       }     }   };    const touchEndHandler = function (ev) {     initialDistance = 0;     initialScale = currentScale;   }; 

在生命周期中定义事件监听与销毁:

定义在afterUpdate中:我们点击图片会显示一个蒙版,图片显示在蒙版上,允许放大和缩小。因此,点击图片时才渲染这个蒙版,imgDetailRef对应的div是条件渲染,若在onMount中定义此事件的监听,此时可能不存在imgDetailRef

若存在imgDetailRef,要先把之前定义的监听移除(removeEventListener),否则会不断地触发监听事件,表示为:当手指捏合操作图片的放大和缩小时,图片的变化显得很卡,且控制台输出一堆信息(console.log写在touchMoveHandler)中。

  afterUpdate(() => {     if (imgDetailRef) {       imgDetailRef.removeEventListener('touchstart', touchStartHandler, false);       imgDetailRef.removeEventListener('touchmove', touchMoveHandler, false);       imgDetailRef.removeEventListener('touchend', touchEndHandler, false);        imgDetailRef.addEventListener('touchstart', touchStartHandler, false);       imgDetailRef.addEventListener('touchmove', touchMoveHandler, false);       imgDetailRef.addEventListener('touchend', touchEndHandler, false);     }   });   onDestroy(() => {     if (imgDetailRef) {       imgDetailRef.removeEventListener('touchstart', touchStartHandler, false);       imgDetailRef.removeEventListener('touchmove', touchMoveHandler, false);       imgDetailRef.removeEventListener('touchend', touchEndHandler, false);     }   }); 

至于蒙版和图片:点击图片时showImageDetail=true等,简单逻辑不赘述。

{:else if showImageDetail}  <div>    <img      class="img-detail"      id="img-detail"      bind:this={imgDetailRef}      src={selectedImage}      alt="selectedImage"    />  </div> {/if} 

如果想在蒙层出现时不允许蒙层下的内容滚动:给不想滚动的类加上此样式(会回到页面顶部)

.no-scroll {     position: fixed;     width: 100%;   } 

或让bodyoverflow:hidden

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!