@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
229 lines (228 loc) • 10.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "ImagePreview", {
enumerable: true,
get: function() {
return ImagePreview;
}
});
var _interop_require_default = require("@swc/helpers/_/_interop_require_default");
var _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
var _object_spread = require("@swc/helpers/_/_object_spread");
var _object_spread_props = require("@swc/helpers/_/_object_spread_props");
var _sliced_to_array = require("@swc/helpers/_/_sliced_to_array");
var _to_consumable_array = require("@swc/helpers/_/_to_consumable_array");
var _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
var _classnames = /*#__PURE__*/ _interop_require_default._(require("classnames"));
var _iconsreact = require("@nutui/icons-react");
var _popup = /*#__PURE__*/ _interop_require_default._(require("../popup"));
var _image = /*#__PURE__*/ _interop_require_default._(require("../image"));
var _video = /*#__PURE__*/ _interop_require_default._(require("../video"));
var _swiper = /*#__PURE__*/ _interop_require_default._(require("../swiper"));
var _swiperitem = /*#__PURE__*/ _interop_require_default._(require("../swiperitem"));
var _typings = require("../../utils/typings");
var _usepropsvalue = require("../../hooks/use-props-value");
var defaultProps = (0, _object_spread_props._)((0, _object_spread._)({}, _typings.ComponentDefaults), {
images: [],
videos: [],
visible: false,
autoPlay: 3000,
defaultValue: 0,
closeOnContentClick: false,
pagination: true,
indicator: false,
indicatorColor: '#fff',
closeIcon: false,
closeIconPosition: 'top-right',
onChange: function onChange() {},
onClose: function onClose() {}
});
var ImagePreview = function ImagePreview(props) {
var _$_object_spread = (0, _object_spread._)({}, defaultProps, props), value = _$_object_spread.value, className = _$_object_spread.className, style = _$_object_spread.style, images = _$_object_spread.images, videos = _$_object_spread.videos, visible = _$_object_spread.visible, defaultValue = _$_object_spread.defaultValue, indicatorColor = _$_object_spread.indicatorColor, pagination = _$_object_spread.pagination, indicator = _$_object_spread.indicator, autoPlay = _$_object_spread.autoPlay, closeOnContentClick = _$_object_spread.closeOnContentClick, closeIcon = _$_object_spread.closeIcon, closeIconPosition = _$_object_spread.closeIconPosition, onClose = _$_object_spread.onClose, onChange = _$_object_spread.onChange;
var classPrefix = 'nut-imagepreview';
var ref = (0, _react.useRef)(null);
var _usePropsValue = (0, _sliced_to_array._)((0, _usepropsvalue.usePropsValue)({
value: value,
defaultValue: defaultValue,
finalValue: defaultValue,
onChange: onChange
}), 2), innerNo = _usePropsValue[0], setInnerNo = _usePropsValue[1];
var _useState = (0, _sliced_to_array._)((0, _react.useState)(visible), 2), showPop = _useState[0], setShowPop = _useState[1];
var _useState1 = (0, _sliced_to_array._)((0, _react.useState)(0), 2), active = _useState1[0], setActive = _useState1[1];
var _useState2 = (0, _sliced_to_array._)((0, _react.useState)(images.length + videos.length), 2), maxNo = _useState2[0], setMaxNo = _useState2[1];
var _useState3 = (0, _sliced_to_array._)((0, _react.useState)({
scale: 1,
moveable: false,
oriDistance: 0,
originScale: 1
}), 2), store = _useState3[0], setStore = _useState3[1];
var lastTouchEndTime = (0, _react.useRef)(0) // 用来辅助监听双击
;
var onTouchStart = function onTouchStart(event) {
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
// 如果是原尺寸,双击放大;否则回到原尺寸。
var curTouchTime = Date.now();
if (curTouchTime - lastTouchEndTime.current < 100) {
var store1 = store;
store1.scale = store1.scale === 1 ? 2 : 1;
scaleNow();
}
var store11 = store;
store11.moveable = true;
if (events2) {
// 如果开始两指操作,记录初始时刻两指间的距离
store11.oriDistance = getDistance(events, events2);
}
// 取到开始两指操作时的放大(缩小比例),store.scale 存储的是当前的放缩比(相对于标准大小 scale 为 1 的情况的放大缩小比)
store11.originScale = store11.scale;
};
var onTouchMove = function onTouchMove(event) {
if (!store.moveable) return;
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
var store1 = store;
// 双指移动
if (events2) {
var curDistance = getDistance(events, events2);
/** 此处计算倍数,距离放大(缩小) k 倍则 scale 也 扩大(缩小) k 倍。距离放大(缩小)倍数 = 结束时两点距离 除以 开始时两点距离
* 注意此处的 scale 变化是基于 store.scale 的。
* store.scale 是一个暂存值,比如第一次放大 2 倍,则 store.scale 为 2。
* 再次两指触碰的时候,store.originScale 就为 store.scale 的值,基于此时的 store.scale 继续放大缩小。 * */ var curScale = curDistance / store1.oriDistance;
// 最大放大 3 倍,缩小后松手要弹回原比例
store1.scale = Math.min(store1.originScale * curScale, 3);
scaleNow();
}
};
var onTouchEnd = function onTouchEnd() {
lastTouchEndTime.current = Date.now();
var store1 = store;
store1.moveable = false;
if (store1.scale < 1.1 && store1.scale > 1 || store1.scale < 1) {
store1.scale = 1;
scaleNow();
}
};
(0, _react.useEffect)(function() {
init();
}, []);
var init = function init() {
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', onTouchEnd);
document.addEventListener('touchcancel', onTouchEnd);
return function() {
document.removeEventListener('touchcancel', onTouchEnd);
document.removeEventListener('touchmove', onTouchMove);
document.removeEventListener('touchend', onTouchEnd);
};
};
(0, _react.useEffect)(function() {
setShowPop(visible);
}, [
visible
]);
(0, _react.useEffect)(function() {
setInnerNo(defaultValue || 1);
}, [
defaultValue
]);
(0, _react.useEffect)(function() {
setActive(innerNo);
}, [
innerNo
]);
(0, _react.useEffect)(function() {
setMaxNo(images.length + videos.length);
}, [
images,
videos
]);
var scaleNow = function scaleNow() {
if (ref.current) {
ref.current.style.transform = "scale(".concat(store.scale, ")");
}
};
// 用于查找给定数字的斜边。起止两点间距离。
var getDistance = function getDistance(first, second) {
return Math.hypot(Math.abs(second.pageX - first.pageX), Math.abs(second.pageY - first.pageY));
};
var slideChangeEnd = function slideChangeEnd(page) {
setActive(page + 1);
onChange === null || onChange === void 0 ? void 0 : onChange(page + 1);
};
var onCloseInner = function onCloseInner(e) {
e.stopPropagation();
setShowPop(false);
setActive(innerNo);
scaleNow();
onClose === null || onClose === void 0 ? void 0 : onClose();
setStore((0, _object_spread_props._)((0, _object_spread._)({}, store), {
scale: 1
}));
};
var closeOnImg = function closeOnImg(e) {
e.stopPropagation();
// 点击内容区域的图片是否可以关闭弹层(视频区域由于nut-video做了限制,无法关闭弹层)
if (closeOnContentClick) onCloseInner(e);
};
var duration = typeof autoPlay === 'string' ? parseInt(autoPlay) : autoPlay;
return /*#__PURE__*/ _react.default.createElement(_popup.default, {
visible: showPop,
className: "".concat(classPrefix, "-pop"),
onClick: onCloseInner
}, /*#__PURE__*/ _react.default.createElement("div", {
className: (0, _classnames.default)(classPrefix, className),
style: style,
ref: ref,
onTouchStart: onTouchStart
}, showPop && /*#__PURE__*/ _react.default.createElement(_swiper.default, {
autoPlay: !!duration,
duration: duration,
className: "".concat(classPrefix, "-swiper"),
loop: true,
style: {
'--nutui-indicator-color': indicatorColor
},
direction: "horizontal",
onChange: function onChange(page) {
return slideChangeEnd(page);
},
defaultValue: innerNo > maxNo ? maxNo - 1 : innerNo - 1,
indicator: indicator
}, (0, _to_consumable_array._)(videos.map(function(item) {
return {
type: 'video',
data: item
};
})).concat((0, _to_consumable_array._)(images.map(function(item) {
return {
type: 'image',
data: item
};
}))).sort(function(a, b) {
var _a_data_index, _b_data_index;
return ((_a_data_index = a.data.index) !== null && _a_data_index !== void 0 ? _a_data_index : 0) - ((_b_data_index = b.data.index) !== null && _b_data_index !== void 0 ? _b_data_index : 0);
}).map(function(item, index) {
return /*#__PURE__*/ _react.default.createElement(_swiperitem.default, {
key: index
}, item.type === 'video' ? /*#__PURE__*/ _react.default.createElement(_video.default, {
source: item.data.source,
options: item.data.options,
onClick: closeOnImg
}) : /*#__PURE__*/ _react.default.createElement(_image.default, {
src: item.data.src,
draggable: false,
onClick: closeOnImg
}));
}))), pagination && /*#__PURE__*/ _react.default.createElement("div", {
className: "".concat(classPrefix, "-index")
}, active, "/", maxNo), closeIcon !== false && /*#__PURE__*/ _react.default.createElement("div", {
className: "".concat(classPrefix, "-close ").concat(closeIconPosition),
onClick: onCloseInner
}, closeIcon === true ? /*#__PURE__*/ _react.default.createElement(_iconsreact.Close, null) : closeIcon));
};
ImagePreview.displayName = 'NutImagePreview';