gui-one-nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
215 lines (214 loc) • 8.04 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
import React__default, { useRef, useState, useEffect } from 'react';
import { P as Popup } from './popup.taro-33d0bbc8.js';
import { S as Swiper } from './swiper.taro-f314d67a.js';
import { S as SwiperItem } from './swiperitem-86a3578a.js';
var defaultProps = {
images: [],
videos: [],
show: false,
autoplay: 3000,
initNo: 1,
contentClose: false,
paginationVisible: false,
paginationColor: '#fff',
onClose: function onClose() {}
};
var ImagePreview = function ImagePreview(props) {
var images = props.images,
videos = props.videos,
show = props.show,
initNo = props.initNo,
paginationColor = props.paginationColor,
paginationVisible = props.paginationVisible,
autoplay = props.autoplay,
contentClose = props.contentClose,
onClose = props.onClose;
var nutImagePreview = useRef(null);
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
showPop = _useState2[0],
setShowPop = _useState2[1];
var _useState3 = useState(1),
_useState4 = _slicedToArray(_useState3, 2),
active = _useState4[0],
setActive = _useState4[1];
var _useState5 = useState(1),
_useState6 = _slicedToArray(_useState5, 2),
maxNo = _useState6[0],
setMaxNo = _useState6[1];
var _useState7 = useState({
scale: 1,
moveable: false
}),
_useState8 = _slicedToArray(_useState7, 2),
store = _useState8[0],
setStore = _useState8[1];
var _useState9 = useState(0),
_useState10 = _slicedToArray(_useState9, 2),
lastTouchEndTime = _useState10[0],
setLastTouchEndTime = _useState10[1]; // 用来辅助监听双击
var onTouchStart = function onTouchStart(event) {
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
// 如果已经放大,双击应变回原尺寸;如果是原尺寸,双击应放大
var curTouchTime = new Date().getTime();
if (curTouchTime - lastTouchEndTime < 300) {
var _store = store;
if (_store.scale > 1) {
_store.scale = 1;
} else if (_store.scale === 1) {
_store.scale = 2;
}
scaleNow();
}
var store1 = store;
store1.moveable = true;
if (events2) {
// 如果开始两指操作,记录初始时刻两指间的距离
store1.oriDistance = getDistance({
x: events.pageX,
y: events.pageY
}, {
x: events2.pageX,
y: events2.pageY
});
}
// 取到开始两指操作时的放大(缩小比例),store.scale 存储的是当前的放缩比(相对于标准大小 scale 为 1 的情况的放大缩小比)
store1.originScale = store1.scale || 1;
};
var onTouchMove = function onTouchMove(event) {
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
if (!store.moveable) {
return;
}
var store1 = store;
// 双指移动
if (events2) {
// 获得当前两点间的距离
var curDistance = getDistance({
x: events.pageX,
y: events.pageY
}, {
x: events2.pageX,
y: events2.pageY
});
/** 此处计算倍数,距离放大(缩小) k 倍则 scale 也 扩大(缩小) k 倍。距离放大(缩小)倍数 = 结束时两点距离 除以 开始时两点距离
* 注意此处的 scale 变化是基于 store.scale 的。
* store.scale 是一个暂存值,比如第一次放大 2 倍,则 store.scale 为 2。
* 再次两指触碰的时候,store.originScale 就为 store.scale 的值,基于此时的 store.scale 继续放大缩小。 * */
var curScale = curDistance / store1.oriDistance;
store1.scale = store1.originScale * curScale;
// 最大放大 3 倍,缩小后松手要弹回原比例
if (store1.scale > 3) {
store1.scale = 3;
}
scaleNow();
}
};
var onTouchEnd = function onTouchEnd() {
setLastTouchEndTime(new Date().getTime());
var store1 = store;
store1.moveable = false;
if (store1.scale < 1.1 && store1.scale > 1 || store1.scale < 1) {
store1.scale = 1;
scaleNow();
}
};
var init = function init() {
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', onTouchEnd);
document.addEventListener('touchcancel', onTouchEnd);
};
useEffect(function () {
if (show !== undefined) {
setShowPop(show);
init();
}
}, [show]);
useEffect(function () {
if (initNo !== undefined) {
setActive(initNo);
}
if (show !== undefined) {
setShowPop(show);
}
if (images && videos) {
setMaxNo(images.length + videos.length);
}
}, []);
var scaleNow = function scaleNow() {
if (nutImagePreview.current) {
nutImagePreview.current.style.transform = "scale(".concat(store.scale, ")");
}
};
var onCloseInner = function onCloseInner() {
setShowPop(false);
setActive(1);
scaleNow();
onClose && onClose();
setStore(_objectSpread(_objectSpread({}, store), {}, {
scale: 1
}));
};
// 计算两个点的距离
var getDistance = function getDistance(first, second) {
// 计算两个点起始时刻的距离和终止时刻的距离,终止时刻距离变大了则放大,变小了则缩小
// 放大 k 倍则 scale 也 扩大 k 倍
return Math.hypot(Math.abs(second.x - first.x), Math.abs(second.y - first.y));
};
var slideChangeEnd = function slideChangeEnd(page) {
setActive(page + 1);
};
var closeOnImg = function closeOnImg() {
// 点击内容区域的图片是否可以关闭弹层(视频区域由于nut-video做了限制,无法关闭弹层)
if (contentClose) {
onCloseInner();
}
};
return React__default.createElement(Popup, {
visible: showPop,
popClass: "custom-pop",
style: {
width: '100%'
},
onClick: onCloseInner
}, React__default.createElement("div", {
className: "nut-imagepreview",
ref: nutImagePreview,
onClick: closeOnImg,
onTouchStart: onTouchStart
}, React__default.createElement(Swiper, {
autoPlay: autoplay,
className: "nut-imagepreview-swiper",
loop: true,
isPreventDefault: false,
style: {
display: showPop ? 'block' : 'none'
},
direction: "horizontal",
onChange: slideChangeEnd,
initPage: initNo && (initNo > maxNo ? maxNo - 1 : initNo - 1),
paginationColor: paginationColor,
paginationVisible: paginationVisible
}, images && images.length > 0 ? images.map(function (item, index) {
return React__default.createElement(SwiperItem, {
key: index
}, React__default.createElement("img", {
src: item.src,
alt: "",
className: "nut-imagepreview-img"
}));
}) : [])), React__default.createElement("div", {
className: "nut-imagepreview-index"
}, active, "/", (images ? images.length : 0) + (videos ? videos.length : 0)));
};
ImagePreview.defaultProps = defaultProps;
ImagePreview.displayName = 'NutImagePreview';
export { ImagePreview as I };