var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var stdin_exports = {}; __export(stdin_exports, { default: () => stdin_default }); module.exports = __toCommonJS(stdin_exports); var import_vue = require("vue"); var import_vue2 = require("vue"); var import_utils = require("../utils"); var import_use_touch = require("../composables/use-touch"); var import_use = require("@vant/use"); var import_image = require("../image"); var import_loading = require("../loading"); var import_swipe_item = require("../swipe-item"); const getDistance = (touches) => Math.sqrt((touches[0].clientX - touches[1].clientX) ** 2 + (touches[0].clientY - touches[1].clientY) ** 2); const bem = (0, import_utils.createNamespace)("image-preview")[1]; var stdin_default = (0, import_vue2.defineComponent)({ props: { src: String, show: Boolean, active: Number, minZoom: (0, import_utils.makeRequiredProp)(import_utils.numericProp), maxZoom: (0, import_utils.makeRequiredProp)(import_utils.numericProp), rootWidth: (0, import_utils.makeRequiredProp)(Number), rootHeight: (0, import_utils.makeRequiredProp)(Number) }, emits: ["scale", "close"], setup(props, { emit, slots }) { const state = (0, import_vue2.reactive)({ scale: 1, moveX: 0, moveY: 0, moving: false, zooming: false, imageRatio: 0, displayWidth: 0, displayHeight: 0 }); const touch = (0, import_use_touch.useTouch)(); const swipeItem = (0, import_vue2.ref)(); const vertical = (0, import_vue2.computed)(() => { const { rootWidth, rootHeight } = props; const rootRatio = rootHeight / rootWidth; return state.imageRatio > rootRatio; }); const imageStyle = (0, import_vue2.computed)(() => { const { scale, moveX, moveY, moving, zooming } = state; const style = { transitionDuration: zooming || moving ? "0s" : ".3s" }; if (scale !== 1) { const offsetX = moveX / scale; const offsetY = moveY / scale; style.transform = `scale(${scale}, ${scale}) translate(${offsetX}px, ${offsetY}px)`; } return style; }); const maxMoveX = (0, import_vue2.computed)(() => { if (state.imageRatio) { const { rootWidth, rootHeight } = props; const displayWidth = vertical.value ? rootHeight / state.imageRatio : rootWidth; return Math.max(0, (state.scale * displayWidth - rootWidth) / 2); } return 0; }); const maxMoveY = (0, import_vue2.computed)(() => { if (state.imageRatio) { const { rootWidth, rootHeight } = props; const displayHeight = vertical.value ? rootHeight : rootWidth * state.imageRatio; return Math.max(0, (state.scale * displayHeight - rootHeight) / 2); } return 0; }); const setScale = (scale) => { scale = (0, import_utils.clamp)(scale, +props.minZoom, +props.maxZoom + 1); if (scale !== state.scale) { state.scale = scale; emit("scale", { scale, index: props.active }); } }; const resetScale = () => { setScale(1); state.moveX = 0; state.moveY = 0; }; const toggleScale = () => { const scale = state.scale > 1 ? 1 : 2; setScale(scale); state.moveX = 0; state.moveY = 0; }; let fingerNum; let startMoveX; let startMoveY; let startScale; let startDistance; let doubleTapTimer; let touchStartTime; const onTouchStart = (event) => { const { touches } = event; const { offsetX } = touch; touch.start(event); fingerNum = touches.length; startMoveX = state.moveX; startMoveY = state.moveY; touchStartTime = Date.now(); state.moving = fingerNum === 1 && state.scale !== 1; state.zooming = fingerNum === 2 && !offsetX.value; if (state.zooming) { startScale = state.scale; startDistance = getDistance(event.touches); } }; const onTouchMove = (event) => { const { touches } = event; touch.move(event); if (state.moving || state.zooming) { (0, import_utils.preventDefault)(event, true); } if (state.moving) { const { deltaX, deltaY } = touch; const moveX = deltaX.value + startMoveX; const moveY = deltaY.value + startMoveY; state.moveX = (0, import_utils.clamp)(moveX, -maxMoveX.value, maxMoveX.value); state.moveY = (0, import_utils.clamp)(moveY, -maxMoveY.value, maxMoveY.value); } if (state.zooming && touches.length === 2) { const distance = getDistance(touches); const scale = startScale * distance / startDistance; setScale(scale); } }; const checkTap = () => { if (fingerNum > 1) { return; } const { offsetX, offsetY } = touch; const deltaTime = Date.now() - touchStartTime; const TAP_TIME = 250; const TAP_OFFSET = 5; if (offsetX.value < TAP_OFFSET && offsetY.value < TAP_OFFSET && deltaTime < TAP_TIME) { if (doubleTapTimer) { clearTimeout(doubleTapTimer); doubleTapTimer = null; toggleScale(); } else { doubleTapTimer = setTimeout(() => { emit("close"); doubleTapTimer = null; }, TAP_TIME); } } }; const onTouchEnd = (event) => { let stopPropagation = false; if (state.moving || state.zooming) { stopPropagation = true; if (state.moving && startMoveX === state.moveX && startMoveY === state.moveY) { stopPropagation = false; } if (!event.touches.length) { if (state.zooming) { state.moveX = (0, import_utils.clamp)(state.moveX, -maxMoveX.value, maxMoveX.value); state.moveY = (0, import_utils.clamp)(state.moveY, -maxMoveY.value, maxMoveY.value); state.zooming = false; } state.moving = false; startMoveX = 0; startMoveY = 0; startScale = 1; if (state.scale < 1) { resetScale(); } if (state.scale > props.maxZoom) { state.scale = +props.maxZoom; } } } (0, import_utils.preventDefault)(event, stopPropagation); checkTap(); touch.reset(); }; const onLoad = (event) => { const { naturalWidth, naturalHeight } = event.target; state.imageRatio = naturalHeight / naturalWidth; }; (0, import_vue2.watch)(() => props.active, resetScale); (0, import_vue2.watch)(() => props.show, (value) => { if (!value) { resetScale(); } }); (0, import_use.useEventListener)("touchmove", onTouchMove, { target: (0, import_vue2.computed)(() => { var _a; return (_a = swipeItem.value) == null ? void 0 : _a.$el; }) }); return () => { const imageSlots = { loading: () => (0, import_vue.createVNode)(import_loading.Loading, { "type": "spinner" }, null) }; return (0, import_vue.createVNode)(import_swipe_item.SwipeItem, { "ref": swipeItem, "class": bem("swipe-item"), "onTouchstartPassive": onTouchStart, "onTouchend": onTouchEnd, "onTouchcancel": onTouchEnd }, { default: () => [slots.image ? (0, import_vue.createVNode)("div", { "class": bem("image-wrap") }, [slots.image({ src: props.src })]) : (0, import_vue.createVNode)(import_image.Image, { "src": props.src, "fit": "contain", "class": bem("image", { vertical: vertical.value }), "style": imageStyle.value, "onLoad": onLoad }, imageSlots)] }); }; } });