/**
|
* 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) => {
|
const k = (p1.y - p2.y) / (p1.x - p2.x);
|
const b = p1.y - k * p1.x;
|
return { k, b };
|
};
|
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')) || 0;
|
startOffsetY = parseInt($img.css('top')) || 0;
|
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.k * scale + equationX.b;
|
const top = equationY.k * scale + equationY.b;
|
// 渲染
|
$img.css({
|
transform: 'scale(' + scale + ')',
|
left,
|
top,
|
});
|
}
|
},
|
touchend: evt => {
|
if (evt.touches.length == 0) {
|
zooming = false;
|
}
|
},
|
});
|
});
|
}, 100);
|
},
|
},
|
};
|
</script>
|