New file |
| | |
| | | /** |
| | | * CImagePreview |
| | | * @author Tevin |
| | | */ |
| | | |
| | | <template> |
| | | <view class="c-image-preview"></view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Taro from '@tarojs/taro'; |
| | | import { $ } from '@tarojs/extend'; |
| | | |
| | | // 直线方程,点斜式参数 |
| | | const createLineEquation = (p1, p2) => ({ |
| | | k: (p1.y - p2.y) / (p1.x - p2.x), |
| | | b: p1.y - k * p1.x, |
| | | }); |
| | | const winWidth = window.innerWidth; |
| | | |
| | | export default { |
| | | name: 'CImagePreview', |
| | | data() { |
| | | return {}; |
| | | }, |
| | | methods: { |
| | | $preview(option) { |
| | | // 网页模式下,增加缩放操作 |
| | | if (process.env.TARO_ENV === 'h5') { |
| | | Taro.previewImage({ |
| | | ...option, |
| | | success: () => { |
| | | this._bindZoomEvent(); |
| | | option.success && option.success(); |
| | | }, |
| | | }); |
| | | } |
| | | // 小程序模式,直接支持缩放 |
| | | else { |
| | | Taro.previewImage({ |
| | | current: file.url, // 当前显示图片的http链接 |
| | | urls, // 需要预览的图片http链接列表 |
| | | }); |
| | | } |
| | | }, |
| | | _bindZoomEvent() { |
| | | const $previewImage = $('.preview-image'); |
| | | setTimeout(() => { |
| | | $previewImage.find('.swiper-slide').css({ overflow: 'hidden' }); |
| | | $previewImage.find('img').each((idx, elm) => { |
| | | const $img = $(elm); |
| | | const defaultWidth = elm.width; |
| | | $img.css({ |
| | | width: defaultWidth, |
| | | maxWidth: '', |
| | | position: 'relative', |
| | | }); |
| | | let startX = 0; |
| | | let startY = 0; |
| | | let startOffsetX = 0; |
| | | let startOffsetY = 0; |
| | | let startWidth = 0; |
| | | let zooming = false; |
| | | let distance = 0; |
| | | let scale = 1; |
| | | let equationX = {}; |
| | | let equationY = {}; |
| | | $img.on({ |
| | | touchstart: evt => { |
| | | startOffsetX = parseInt($img.css('left')); |
| | | startOffsetY = parseInt($img.css('top')); |
| | | startWidth = parseInt($img.css('width')) * scale; |
| | | if (evt.touches.length == 1) { |
| | | const { clientX, clientY } = evt.touches[0]; |
| | | startX = clientX; |
| | | startY = clientY; |
| | | } else { |
| | | const xMove = |
| | | evt.touches[1].clientX - evt.touches[0].clientX; |
| | | const yMove = |
| | | evt.touches[1].clientY - evt.touches[0].clientY; |
| | | distance = Math.sqrt(xMove * xMove + yMove * yMove); |
| | | zooming = true; |
| | | // 已放大过了 |
| | | if (scale - 1 > 0.1) { |
| | | equationX = createLineEquation( |
| | | { x: 1, y: 0 }, |
| | | { x: scale, y: startOffsetX } |
| | | ); |
| | | equationY = createLineEquation( |
| | | { x: 1, y: 0 }, |
| | | { x: scale, y: startOffsetY } |
| | | ); |
| | | } |
| | | // 初始状态,不线性计算 |
| | | else { |
| | | equationX = equationY = { k: 0, b: 0 }; |
| | | } |
| | | } |
| | | }, |
| | | touchmove: evt => { |
| | | if (evt.touches.length == 1) { |
| | | //单指移动,缩放状态,不处理单指 |
| | | if (zooming) { |
| | | return; |
| | | } |
| | | const { clientX, clientY } = evt.touches[0]; |
| | | const left = clientX - startX + startOffsetX; |
| | | const top = clientY - startY + startOffsetY; |
| | | // 限制大小 |
| | | const limitSize = (startWidth - winWidth) / 2; |
| | | // 在限制大小范围内,移动图片自身 |
| | | if (left >= -limitSize && left <= limitSize) { |
| | | $img.css({ top, left }); |
| | | // 阻止冒泡 |
| | | evt.preventDefault(); |
| | | evt.stopPropagation(); |
| | | } |
| | | // 超出限制大小不操作,冒泡翻页 |
| | | else { |
| | | } |
| | | } else { |
| | | //双指缩放 |
| | | const xMove = |
| | | evt.touches[1].clientX - evt.touches[0].clientX; |
| | | const yMove = |
| | | evt.touches[1].clientY - evt.touches[0].clientY; |
| | | const newDistance = Math.sqrt( |
| | | xMove * xMove + yMove * yMove |
| | | ); |
| | | const distanceDiff = newDistance - distance; |
| | | const newScale = scale + 0.01 * distanceDiff; |
| | | // 缩放比例设置 |
| | | if (newScale <= 5 && newScale >= 1) { |
| | | distance = newDistance; |
| | | scale = newScale; |
| | | } else { |
| | | if (newScale > 5) { |
| | | scale = 5; |
| | | } else if (newScale < 1) { |
| | | scale = 1; |
| | | } |
| | | } |
| | | // 修正位置 |
| | | const left = equationX.a * scale + equationX.b; |
| | | const top = equationY.a * scale + equationY.b; |
| | | // 渲染 |
| | | $img.css({ |
| | | transform: 'scale(' + scale + ')', |
| | | left, |
| | | top, |
| | | }); |
| | | } |
| | | }, |
| | | touchend: evt => { |
| | | if (evt.touches.length == 0) { |
| | | zooming = false; |
| | | } |
| | | }, |
| | | }); |
| | | }); |
| | | }, 100); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |