| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 | import { createVNode as _createVNode } from "vue";import { ref, watch, computed, reactive, defineComponent } from "vue";import { clamp, numericProp, preventDefault, createNamespace, makeRequiredProp } from "../utils/index.mjs";import { useTouch } from "../composables/use-touch.mjs";import { useEventListener } from "@vant/use";import { Image } from "../image/index.mjs";import { Loading } from "../loading/index.mjs";import { SwipeItem } from "../swipe-item/index.mjs";const getDistance = (touches) => Math.sqrt((touches[0].clientX - touches[1].clientX) ** 2 + (touches[0].clientY - touches[1].clientY) ** 2);const bem = createNamespace("image-preview")[1];var stdin_default = defineComponent({  props: {    src: String,    show: Boolean,    active: Number,    minZoom: makeRequiredProp(numericProp),    maxZoom: makeRequiredProp(numericProp),    rootWidth: makeRequiredProp(Number),    rootHeight: makeRequiredProp(Number)  },  emits: ["scale", "close"],  setup(props, {    emit,    slots  }) {    const state = reactive({      scale: 1,      moveX: 0,      moveY: 0,      moving: false,      zooming: false,      imageRatio: 0,      displayWidth: 0,      displayHeight: 0    });    const touch = useTouch();    const swipeItem = ref();    const vertical = computed(() => {      const {        rootWidth,        rootHeight      } = props;      const rootRatio = rootHeight / rootWidth;      return state.imageRatio > rootRatio;    });    const imageStyle = 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 = 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 = 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 = 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) {        preventDefault(event, true);      }      if (state.moving) {        const {          deltaX,          deltaY        } = touch;        const moveX = deltaX.value + startMoveX;        const moveY = deltaY.value + startMoveY;        state.moveX = clamp(moveX, -maxMoveX.value, maxMoveX.value);        state.moveY = 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 = clamp(state.moveX, -maxMoveX.value, maxMoveX.value);            state.moveY = 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;          }        }      }      preventDefault(event, stopPropagation);      checkTap();      touch.reset();    };    const onLoad = (event) => {      const {        naturalWidth,        naturalHeight      } = event.target;      state.imageRatio = naturalHeight / naturalWidth;    };    watch(() => props.active, resetScale);    watch(() => props.show, (value) => {      if (!value) {        resetScale();      }    });    useEventListener("touchmove", onTouchMove, {      target: computed(() => {        var _a;        return (_a = swipeItem.value) == null ? void 0 : _a.$el;      })    });    return () => {      const imageSlots = {        loading: () => _createVNode(Loading, {          "type": "spinner"        }, null)      };      return _createVNode(SwipeItem, {        "ref": swipeItem,        "class": bem("swipe-item"),        "onTouchstartPassive": onTouchStart,        "onTouchend": onTouchEnd,        "onTouchcancel": onTouchEnd      }, {        default: () => [slots.image ? _createVNode("div", {          "class": bem("image-wrap")        }, [slots.image({          src: props.src        })]) : _createVNode(Image, {          "src": props.src,          "fit": "contain",          "class": bem("image", {            vertical: vertical.value          }),          "style": imageStyle.value,          "onLoad": onLoad        }, imageSlots)]      });    };  }});export {  stdin_default as default};
 |