From ec3f9f1abaf2b0327a69ac7b223120f594986d03 Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Fri, 23 Sep 2022 20:48:38 +0800 Subject: [PATCH] 上传图片前预览,支持H5模式下的双指缩放 --- forms/imagePicker/CImagePicker.vue | 6 + forms/imagePicker/CImagePreview.vue | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 1 deletions(-) diff --git a/forms/imagePicker/CImagePicker.vue b/forms/imagePicker/CImagePicker.vue index 6ebd882..fc22f85 100644 --- a/forms/imagePicker/CImagePicker.vue +++ b/forms/imagePicker/CImagePicker.vue @@ -25,6 +25,7 @@ :onImageClick="(index, file)=>handleImgView(index,file)" /> <CImageCompressor ref="compressor" /> + <CImagePreview ref="imgPreview" /> </view> </template> @@ -36,12 +37,14 @@ import { $fetchCommon } from '@fetchers/FCommon'; import { Tools } from '@components/common/Tools'; import CImageCompressor from './CImageCompressor.vue'; +import CImagePreview from './CImagePreview.vue'; import './cImagePicker.scss'; export default { name: 'CImagePicker', components: { CImageCompressor, + CImagePreview, AtInput, AtImagePicker, AtCurtain, @@ -158,7 +161,8 @@ const urls = this.files .map(file => (file.type === 'btn' ? false : file.url)) .filter(Boolean); - Taro.previewImage({ + // 图片预览,支持H5模式下的双指缩放 + this.$refs.imgPreview.$preview({ current: file.url, // 当前显示图片的http链接 urls, // 需要预览的图片http链接列表 }); diff --git a/forms/imagePicker/CImagePreview.vue b/forms/imagePicker/CImagePreview.vue new file mode 100644 index 0000000..cb615de --- /dev/null +++ b/forms/imagePicker/CImagePreview.vue @@ -0,0 +1,166 @@ +/** + * 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> \ No newline at end of file -- Gitblit v1.9.1