123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- import { ref, watch, nextTick, reactive, onMounted, defineComponent, createVNode as _createVNode, mergeProps as _mergeProps } from "vue";
- import { pick, truthProp, unknownProp, windowWidth, windowHeight, makeArrayProp, makeStringProp, makeNumericProp, callInterceptor, createNamespace, HAPTICS_FEEDBACK } from "../utils/index.mjs";
- import { useRect } from "@vant/use";
- import { useExpose } from "../composables/use-expose.mjs";
- import { Icon } from "../icon/index.mjs";
- import { Swipe } from "../swipe/index.mjs";
- import { Popup } from "../popup/index.mjs";
- import ImagePreviewItem from "./ImagePreviewItem.mjs";
- const [name, bem] = createNamespace("image-preview");
- const popupProps = ["show", "teleport", "transition", "overlayStyle", "closeOnPopstate"];
- const imagePreviewProps = {
- show: Boolean,
- loop: truthProp,
- images: makeArrayProp(),
- minZoom: makeNumericProp(1 / 3),
- maxZoom: makeNumericProp(3),
- overlay: truthProp,
- vertical: Boolean,
- closeable: Boolean,
- showIndex: truthProp,
- className: unknownProp,
- closeIcon: makeStringProp("clear"),
- transition: String,
- beforeClose: Function,
- doubleScale: truthProp,
- overlayClass: unknownProp,
- overlayStyle: Object,
- swipeDuration: makeNumericProp(300),
- startPosition: makeNumericProp(0),
- showIndicators: Boolean,
- closeOnPopstate: truthProp,
- closeOnClickImage: truthProp,
- closeOnClickOverlay: truthProp,
- closeIconPosition: makeStringProp("top-right"),
- teleport: [String, Object]
- };
- var stdin_default = defineComponent({
- name,
- props: imagePreviewProps,
- emits: ["scale", "close", "closed", "change", "longPress", "update:show"],
- setup(props, {
- emit,
- slots
- }) {
- const swipeRef = ref();
- const activedPreviewItemRef = ref();
- const state = reactive({
- active: 0,
- rootWidth: 0,
- rootHeight: 0,
- disableZoom: false
- });
- const resize = () => {
- if (swipeRef.value) {
- const rect = useRect(swipeRef.value.$el);
- state.rootWidth = rect.width;
- state.rootHeight = rect.height;
- swipeRef.value.resize();
- }
- };
- const emitScale = (args) => emit("scale", args);
- const updateShow = (show) => emit("update:show", show);
- const emitClose = () => {
- callInterceptor(props.beforeClose, {
- args: [state.active],
- done: () => updateShow(false)
- });
- };
- const setActive = (active) => {
- if (active !== state.active) {
- state.active = active;
- emit("change", active);
- }
- };
- const renderIndex = () => {
- if (props.showIndex) {
- return _createVNode("div", {
- "class": bem("index")
- }, [slots.index ? slots.index({
- index: state.active
- }) : `${state.active + 1} / ${props.images.length}`]);
- }
- };
- const renderCover = () => {
- if (slots.cover) {
- return _createVNode("div", {
- "class": bem("cover")
- }, [slots.cover()]);
- }
- };
- const onDragStart = () => {
- state.disableZoom = true;
- };
- const onDragEnd = () => {
- state.disableZoom = false;
- };
- const renderImages = () => _createVNode(Swipe, {
- "ref": swipeRef,
- "lazyRender": true,
- "loop": props.loop,
- "class": bem("swipe"),
- "vertical": props.vertical,
- "duration": props.swipeDuration,
- "initialSwipe": props.startPosition,
- "showIndicators": props.showIndicators,
- "indicatorColor": "white",
- "onChange": setActive,
- "onDragEnd": onDragEnd,
- "onDragStart": onDragStart
- }, {
- default: () => [props.images.map((image, index) => _createVNode(ImagePreviewItem, {
- "ref": (item) => {
- if (index === state.active) {
- activedPreviewItemRef.value = item;
- }
- },
- "src": image,
- "show": props.show,
- "active": state.active,
- "maxZoom": props.maxZoom,
- "minZoom": props.minZoom,
- "rootWidth": state.rootWidth,
- "rootHeight": state.rootHeight,
- "disableZoom": state.disableZoom,
- "doubleScale": props.doubleScale,
- "closeOnClickImage": props.closeOnClickImage,
- "closeOnClickOverlay": props.closeOnClickOverlay,
- "vertical": props.vertical,
- "onScale": emitScale,
- "onClose": emitClose,
- "onLongPress": () => emit("longPress", {
- index
- })
- }, {
- image: slots.image
- }))]
- });
- const renderClose = () => {
- if (props.closeable) {
- return _createVNode(Icon, {
- "role": "button",
- "name": props.closeIcon,
- "class": [bem("close-icon", props.closeIconPosition), HAPTICS_FEEDBACK],
- "onClick": emitClose
- }, null);
- }
- };
- const onClosed = () => emit("closed");
- const swipeTo = (index, options) => {
- var _a;
- return (_a = swipeRef.value) == null ? void 0 : _a.swipeTo(index, options);
- };
- useExpose({
- resetScale: () => {
- var _a;
- (_a = activedPreviewItemRef.value) == null ? void 0 : _a.resetScale();
- },
- swipeTo
- });
- onMounted(resize);
- watch([windowWidth, windowHeight], resize);
- watch(() => props.startPosition, (value) => setActive(+value));
- watch(() => props.show, (value) => {
- const {
- images,
- startPosition
- } = props;
- if (value) {
- setActive(+startPosition);
- nextTick(() => {
- resize();
- swipeTo(+startPosition, {
- immediate: true
- });
- });
- } else {
- emit("close", {
- index: state.active,
- url: images[state.active]
- });
- }
- });
- return () => _createVNode(Popup, _mergeProps({
- "class": [bem(), props.className],
- "overlayClass": [bem("overlay"), props.overlayClass],
- "onClosed": onClosed,
- "onUpdate:show": updateShow
- }, pick(props, popupProps)), {
- default: () => [renderClose(), renderImages(), renderIndex(), renderCover()]
- });
- }
- });
- export {
- stdin_default as default,
- imagePreviewProps
- };
|