tdesign-mobile-vue
Version:
tdesign-mobile-vue
499 lines (491 loc) • 20 kB
JavaScript
/**
* tdesign v1.7.0
* (c) 2024 TDesign Group
* @license MIT
*/
;
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