UNPKG

tdesign-mobile-vue

Version:
499 lines (491 loc) 20 kB
/** * tdesign v1.7.0 * (c) 2024 TDesign Group * @license MIT */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _slicedToArray = require('@babel/runtime/helpers/slicedToArray'); var vue = require('vue'); var tdesignIconsVueNext = require('tdesign-icons-vue-next'); var config = require('../config.js'); var imageViewer_props = require('./props.js'); var hooks_tnode = require('../hooks/tnode.js'); var hooks_useClass = require('../hooks/useClass.js'); var swiper_index = require('../swiper/index.js'); var shared_useGesture_index = require('../shared/useGesture/index.js'); var shared_useDefault_index = require('../shared/useDefault/index.js'); var shared_util = require('../shared/util.js'); require('lodash/isFunction'); require('lodash/camelCase'); require('lodash/kebabCase'); require('../hooks/render-tnode.js'); require('lodash/isEmpty'); require('lodash/isString'); require('lodash/isObject'); require('../config-provider/useConfig.js'); require('@babel/runtime/helpers/defineProperty'); require('lodash/cloneDeep'); require('../config-provider/context.js'); require('lodash/mergeWith'); require('lodash/merge'); require('lodash/isArray'); require('../_common/js/global-config/mobile/default-config.js'); require('../_common/js/global-config/mobile/locale/zh_CN.js'); require('../_chunks/dep-8d930798.js'); require('@babel/runtime/helpers/typeof'); require('../_chunks/dep-a20a5149.js'); require('dayjs'); require('../swiper/swiper.js'); require('lodash/isNumber'); require('../swipe-cell/useSwipe.js'); require('@vueuse/core'); require('../shared/dom.js'); require('../swiper/props.js'); require('../shared/useVModel/index.js'); require('../swiper/swiper-item.js'); require('../shared/component.js'); require('@use-gesture/vanilla'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray); function _isSlot(s) { return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s); } var prefix = config["default"].prefix; var TAP_TIME = 300; var _ImageViewer = vue.defineComponent({ name: "".concat(prefix, "-image-viewer"), props: imageViewer_props["default"], emits: ["close", "index-change", "update:visible", "update:modelValue", "update:index", "delete"], setup: function setup(props2, _ref) { var emit = _ref.emit; var imageViewerClass = hooks_useClass.usePrefixClass("image-viewer"); var state = vue.reactive({ dblTapZooming: false, zooming: false, scale: 1, touchIndex: 0, dragging: false, draggedX: 0, draggedY: 0, extraDraggedX: 0 }); var _useDefault = shared_useDefault_index.useDefault(props2, emit, "visible", "change"), _useDefault2 = _slicedToArray__default["default"](_useDefault, 2), visible = _useDefault2[0], setVisible = _useDefault2[1]; var _useDefault3 = shared_useDefault_index.useDefault(props2, emit, "index", "index-change"), _useDefault4 = _slicedToArray__default["default"](_useDefault3, 2), currentIndex = _useDefault4[0], setIndex = _useDefault4[1]; var preloadImageIndex = vue.computed(function () { var lastIndex = props2.images.length - 1; if ([void 0, 0].includes(currentIndex.value)) { return [0, 1, lastIndex]; } if (currentIndex.value === lastIndex) { return [lastIndex, lastIndex - 1, 0]; } var prev = currentIndex.value - 1 >= 0 ? currentIndex.value - 1 : lastIndex; var next = currentIndex.value + 1 <= lastIndex ? currentIndex.value + 1 : 0; return [currentIndex.value, prev, next]; }); var imageInfoList = vue.computed(function () { return props2.images.map(function (image, index) { var imageInfo; if (typeof image === "string") { imageInfo = { url: image, align: "center" }; } else { imageInfo = image; } return { image: imageInfo, preload: preloadImageIndex.value.includes(index) }; }); }); var disabled = vue.ref(false); var rootRef = vue.ref(); var imagesSize = vue.reactive({}); var swiperRootRef = vue.ref(); var swiperItemRefs = vue.ref([]); var gestureRef = vue.ref(); var renderTNodeJSX = hooks_tnode.useTNodeJSX(); var closeNode = vue.computed(function () { return renderTNodeJSX("closeBtn", vue.h(tdesignIconsVueNext.CloseIcon)); }); var deleteNode = vue.computed(function () { return renderTNodeJSX("deleteBtn", vue.h(tdesignIconsVueNext.DeleteIcon)); }); var imageTransform = vue.computed(function () { var scale = state.scale, draggedX = state.draggedX, draggedY = state.draggedY; return "matrix(".concat(scale, ", 0, 0, ").concat(scale, ", ").concat(draggedX, ", ").concat(draggedY, ")"); }); var imageTransitionDuration = vue.computed(function () { var zooming = state.zooming, dragging = state.dragging; return zooming || dragging ? "transition-duration: 0s" : "transition-duration: 0.3s"; }); var beforeClose = function beforeClose() { state.dblTapZooming = false; state.zooming = false; state.scale = 1; state.dragging = false; state.draggedX = 0; state.draggedY = 0; state.extraDraggedX = 0; }; var handleClose = function handleClose(e, trigger) { beforeClose(); setVisible(false); emit("close", { trigger: trigger, e: e }); }; var handleDelete = function handleDelete() { var _currentIndex$value; emit("delete", (_currentIndex$value = currentIndex.value) !== null && _currentIndex$value !== void 0 ? _currentIndex$value : 0); }; var setImagePreload = function setImagePreload(index) { var nextIndex = index >= imageInfoList.value.length - 1 ? 0 : index + 1; var preIndex = index <= 0 ? imageInfoList.value.length - 1 : index - 1; imageInfoList.value[preIndex].preload = true; imageInfoList.value[nextIndex].preload = true; }; var onSwiperChange = function onSwiperChange(index, context) { if (currentIndex.value !== index) { var trigger = currentIndex.value < index ? "next" : "prev"; setIndex(index, { trigger: trigger }); setScale(1); setImagePreload(index); } }; var onImgLoad = function onImgLoad(e, index) { var height = e.target.height; imagesSize[index] = { height: height }; }; var getMaxDraggedX = function getMaxDraggedX() { var _rootRef$value; var rootOffsetWidth = ((_rootRef$value = rootRef.value) === null || _rootRef$value === void 0 ? void 0 : _rootRef$value.offsetWidth) || 0; var scaledWidth = state.scale * rootOffsetWidth; return Math.max(0, (scaledWidth - rootOffsetWidth) / 2); }; var getMaxDraggedY = function getMaxDraggedY(index) { var _rootRef$value2, _imagesSize$index, _imageInfoList$value$; var rootOffsetHeight = ((_rootRef$value2 = rootRef.value) === null || _rootRef$value2 === void 0 ? void 0 : _rootRef$value2.offsetHeight) || 0; var currentImageHeight = (imagesSize === null || imagesSize === void 0 || (_imagesSize$index = imagesSize[index]) === null || _imagesSize$index === void 0 ? void 0 : _imagesSize$index.height) || 0; var currentImageScaledHeight = state.scale * currentImageHeight; var halfScaleHeight = (currentImageScaledHeight - currentImageHeight) / 2; if (currentImageScaledHeight <= rootOffsetHeight) { return { top: 0, bottom: 0 }; } var diffHeight = currentImageScaledHeight - rootOffsetHeight; var centerDraggedY = diffHeight / 2; var alignmentDraggedY = { start: { top: -diffHeight + halfScaleHeight, bottom: halfScaleHeight }, center: { top: -centerDraggedY, bottom: centerDraggedY }, end: { top: -halfScaleHeight, bottom: diffHeight - halfScaleHeight } }; var alignment = ((_imageInfoList$value$ = imageInfoList.value[index]) === null || _imageInfoList$value$ === void 0 || (_imageInfoList$value$ = _imageInfoList$value$.image) === null || _imageInfoList$value$ === void 0 ? void 0 : _imageInfoList$value$.align) || "center"; return alignmentDraggedY[alignment]; }; var setScale = function setScale(scale) { scale = Math.min(scale, +props2.maxZoom + 1); if (scale !== state.scale) { state.scale = scale; if (scale === 1) { state.draggedX = 0; state.draggedY = 0; } } }; var dragStartTime; var dblTapTimer; var toggleScale = function toggleScale() { var scale = state.scale > 1 ? 1 : 2; setScale(scale); }; var onTransitionEnd = function onTransitionEnd(index) { if (index === state.touchIndex) { state.dblTapZooming = false; clearTimeout(dblTapTimer); dblTapTimer = null; } }; var onTransitionStart = function onTransitionStart(index) { if (index === state.touchIndex) { state.dblTapZooming = true; clearTimeout(dblTapTimer); } }; var checkTap = function checkTap(e) { var event = e.event; var deltaTime = Date.now() - dragStartTime; if (deltaTime < TAP_TIME && shared_util.isBrowser) { if (dblTapTimer) { clearTimeout(dblTapTimer); dblTapTimer = window.setTimeout(function () { clearTimeout(dblTapTimer); state.dragging = false; toggleScale(); }, TAP_TIME); } else { dblTapTimer = window.setTimeout(function () { handleClose(event, "overlay"); dblTapTimer = null; }, TAP_TIME); } } }; var onPinchChange = function onPinchChange(scale, index) { state.zooming = true; state.touchIndex = index; setScale(scale); }; var onPinchEnd = function onPinchEnd() { state.zooming = false; if (state.scale < 1) { setScale(1); } if (state.scale > props2.maxZoom) { state.scale = +props2.maxZoom; } }; var handlePinch = function handlePinch(pinState, index) { var last = pinState.last, _pinState$offset = _slicedToArray__default["default"](pinState.offset, 1), d = _pinState$offset[0]; if (!(imagesSize !== null && imagesSize !== void 0 && imagesSize[index])) return; if (state.dblTapZooming) return; if (!last) { onPinchChange(d, index); } else { onPinchEnd(); } }; var handleDrag = function handleDrag(dragState, index) { state.touchIndex = index; var _ref2 = swiperRootRef.value || {}, setOffset = _ref2.setOffset; if (!(imagesSize !== null && imagesSize !== void 0 && imagesSize[index])) return; var first = dragState.first, movement = dragState.movement, _movement = dragState._movement, elapsedTime = dragState.elapsedTime, tap = dragState.tap, offset = dragState.offset, overflow = dragState.overflow, _delta = dragState._delta; if (first) { dragStartTime = Date.now(); } if (tap && elapsedTime > 0 && elapsedTime < 300) { checkTap(dragState); return; } if (state.dblTapZooming) { dragState === null || dragState === void 0 || dragState.cancel(); return; } state.dragging = true; state.draggedY = (offset === null || offset === void 0 ? void 0 : offset[1]) || 0; if (state.scale === 1) return; state.draggedX = (offset === null || offset === void 0 ? void 0 : offset[0]) || 0; if (movement[0] !== _movement[0] && overflow[0] !== 0) { state.extraDraggedX += _delta[0] / 5; setOffset === null || setOffset === void 0 || setOffset(state.extraDraggedX, "X"); } else if (state.extraDraggedX !== 0) { state.extraDraggedX = 0; setOffset === null || setOffset === void 0 || setOffset(state.extraDraggedX, "X"); } }; var handleDragEnd = function handleDragEnd(dragState) { var overflow = dragState.overflow, last = dragState.last; var _ref3 = swiperRootRef.value || {}, goPrev = _ref3.goPrev, goNext = _ref3.goNext, swiperContainer = _ref3.swiperContainer; state.dragging = false; if (state.extraDraggedX !== 0 && last) { if (Math.abs(state.extraDraggedX) > 50) { state.extraDraggedX = 0; overflow[0] < 0 ? goNext === null || goNext === void 0 ? void 0 : goNext("touch") : goPrev === null || goPrev === void 0 ? void 0 : goPrev("touch"); return; } state.extraDraggedX = 0; vue.nextTick(function () { var _swiperContainer$styl, _swiperContainer$styl2, _swiperContainer$styl3, _swiperContainer$styl4; swiperContainer === null || swiperContainer === void 0 || (_swiperContainer$styl = swiperContainer.style) === null || _swiperContainer$styl === void 0 || (_swiperContainer$styl2 = _swiperContainer$styl.setProperty) === null || _swiperContainer$styl2 === void 0 || _swiperContainer$styl2.call(_swiperContainer$styl, "transform", "translateX(0)"); swiperContainer === null || swiperContainer === void 0 || (_swiperContainer$styl3 = swiperContainer.style) === null || _swiperContainer$styl3 === void 0 || (_swiperContainer$styl4 = _swiperContainer$styl3.setProperty) === null || _swiperContainer$styl4 === void 0 || _swiperContainer$styl4.call(_swiperContainer$styl3, "transition", "transform 0.3s"); }); } }; var gestureOptions = vue.reactive({ destroyInvisible: true, visible: !!visible.value }); gestureRef.value = shared_useGesture_index.useGesture(gestureOptions); vue.watch(function () { return visible.value; }, function (newVal) { return gestureOptions.visible = !!newVal; }); vue.watch(function () { return [visible.value, swiperItemRefs.value]; }, function (_ref4) { var _ref5 = _slicedToArray__default["default"](_ref4, 2), newVisible = _ref5[0], newRefs = _ref5[1]; if (!newVisible) return; vue.nextTick(function () { var _newRefs$forEach; (_newRefs$forEach = newRefs.forEach) === null || _newRefs$forEach === void 0 || _newRefs$forEach.call(newRefs, function (item, index) { var _gestureRef$value; var $el = item.$el; (_gestureRef$value = gestureRef.value) === null || _gestureRef$value === void 0 || _gestureRef$value.create($el, { onDrag: function onDrag(dragState) { return handleDrag(dragState, index); }, onDragEnd: function onDragEnd(dragState) { return handleDragEnd(dragState); }, onPinch: function onPinch(pinchState) { return handlePinch(pinchState, index); } }, { drag: { from: function from() { return [state.draggedX, state.draggedY]; }, pointer: { touch: true }, bounds: function bounds() { return { top: getMaxDraggedY(index).top, right: getMaxDraggedX(), bottom: getMaxDraggedY(index).bottom, left: -getMaxDraggedX() }; } }, pinch: { from: function from() { return [state.scale, 0]; }, pointer: { touch: true } } }); }); }); }); vue.watch(function () { return state.scale; }, function (newVal) { return disabled.value = newVal !== 1; }); vue.onUnmounted(function () { clearTimeout(dblTapTimer); }); return function () { var _currentIndex$value2, _props2$images, _props2$images2; var _slot; return vue.createVNode(vue.Transition, { "name": "fade" }, { default: function _default() { return [visible.value && vue.createVNode("div", { "ref": rootRef, "class": "".concat(imageViewerClass.value) }, [vue.createVNode("div", { "class": "".concat(imageViewerClass.value, "__mask"), "onClick": function onClick(e) { return handleClose(e, "overlay"); } }, null), vue.createVNode(swiper_index.Swiper, { "ref": swiperRootRef, "autoplay": false, "class": "".concat(imageViewerClass.value, "__content"), "height": "100vh", "defaultCurrent": currentIndex.value, "disabled": disabled.value, "onChange": onSwiperChange }, _isSlot(_slot = imageInfoList.value.map(function (info, index) { return vue.createVNode(swiper_index.SwiperItem, { "ref": function ref(item) { return swiperItemRefs.value[index] = item; }, "key": index, "class": "".concat(imageViewerClass.value, "__swiper-item"), "style": "touch-action: none; align-items:".concat(info.image.align, ";") }, { default: function _default() { return [info.preload ? vue.createVNode("img", { "src": info.image.url, "style": "\n transform: ".concat(index === state.touchIndex ? imageTransform.value : "matrix(1, 0, 0, 1, 0, 0)", ";\n ").concat(imageTransitionDuration.value, ";"), "class": "".concat(imageViewerClass.value, "__img"), "onLoad": function onLoad(event) { return onImgLoad(event, index); }, "onTransitionstart": function onTransitionstart(event) { if (event.target === event.currentTarget) { onTransitionStart(index); } }, "onTransitionend": function onTransitionend(event) { if (event.target === event.currentTarget) { onTransitionEnd(index); } } }, null) : vue.createVNode("span", null, null)]; } }); })) ? _slot : { default: function _default() { return [_slot]; } }), vue.createVNode("div", { "class": "".concat(imageViewerClass.value, "__nav") }, [vue.createVNode("div", { "class": "".concat(imageViewerClass.value, "__nav-close"), "onClick": function onClick(e) { return handleClose(e, "close-btn"); } }, [closeNode.value]), props2.showIndex && vue.createVNode("div", { "class": "".concat(imageViewerClass.value, "__nav-index") }, ["".concat(Math.min(((_currentIndex$value2 = currentIndex.value) !== null && _currentIndex$value2 !== void 0 ? _currentIndex$value2 : 0) + 1, (_props2$images = props2.images) === null || _props2$images === void 0 ? void 0 : _props2$images.length), "/").concat((_props2$images2 = props2.images) === null || _props2$images2 === void 0 ? void 0 : _props2$images2.length)]), vue.createVNode("div", { "class": "".concat(imageViewerClass.value, "__nav-delete"), "onClick": handleDelete }, [deleteNode.value])])])]; } }); }; } }); exports["default"] = _ImageViewer; //# sourceMappingURL=image-viewer.js.map