UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

229 lines (228 loc) 10.7 kB
"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';