UNPKG

a-draggable-component

Version:

一个可以托拽的vue3+typescript组件,主要应用场景:两个子空间的拖拽状态的相互转换

619 lines (618 loc) 21.7 kB
import { defineComponent, computed, openBlock, createElementBlock, normalizeStyle, createElementVNode, ref, reactive, Fragment, renderList, renderSlot, mergeDefaults, unref, createBlock, createCommentVNode, onMounted, onUnmounted } from "vue"; if (typeof window !== "undefined") { let loadSvg = function() { var body = document.body; var svgDom = document.getElementById("__svg__icons__dom__"); if (!svgDom) { svgDom = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgDom.style.position = "absolute"; svgDom.style.width = "0"; svgDom.style.height = "0"; svgDom.id = "__svg__icons__dom__"; svgDom.setAttribute("xmlns", "http://www.w3.org/2000/svg"); svgDom.setAttribute("xmlns:link", "http://www.w3.org/1999/xlink"); } svgDom.innerHTML = '<symbol viewBox="64 64 896 896" fill="currentColor" aria-hidden="true" id="icon-arrowRight"><path d="M765.7 486.8 314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z" /></symbol>'; body.insertBefore(svgDom, body.lastChild); }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", loadSvg); } else { loadSvg(); } } const _hoisted_1$1 = ["fill"]; const _hoisted_2$1 = ["xlink:href", "fill"]; const _sfc_main$2 = /* @__PURE__ */ defineComponent({ __name: "index", props: { name: {}, prefix: { default: "icon" }, iconStyle: { default: () => ({ width: "30px", height: "30px" }) }, color: { default: "#333" } }, setup(__props) { const props = __props; const symbolId = computed(() => `#${props.prefix}-${props.name}`); return (_ctx, _cache) => { return openBlock(), createElementBlock("svg", { style: normalizeStyle({ ..._ctx.iconStyle, color: _ctx.color }), "aria-hidden": "true", fill: _ctx.color }, [ createElementVNode("use", { "xlink:href": symbolId.value, fill: _ctx.color }, null, 8, _hoisted_2$1) ], 12, _hoisted_1$1); }; } }); const CallbackMap = /* @__PURE__ */ new WeakMap(); const mouseAddListener = (dom, callbackObj) => { if (CallbackMap.has(dom)) { const list = CallbackMap.get(dom); list.push(callbackObj); CallbackMap.set(dom, list); } else { CallbackMap.set(dom, [callbackObj]); } if (callbackObj.mousemoveFn) { dom.addEventListener("mousemove", (e) => { callbackObj.mousemoveFn(e, dom); }); } if (callbackObj.mouseupFn) { dom.addEventListener("mouseup", (e) => { callbackObj.mouseupFn(e, dom); }); } if (callbackObj.mousedownFn) { dom.addEventListener("mousedown", (e) => { callbackObj.mousedownFn(e, dom); }); } }; const mouseRemoveListener = (dom) => { const callbackObjList = CallbackMap.get(dom); if (callbackObjList && callbackObjList.length) { callbackObjList.forEach((callbackObj) => { if (callbackObj.mousemoveFn) { dom.removeEventListener("mousemove", callbackObj.mousemoveFn); } if (callbackObj.mouseupFn) { dom.removeEventListener("mouseup", callbackObj.mouseupFn); } if (callbackObj.mousedownFn) { dom.removeEventListener("mousedown", callbackObj.mousedownFn); } }); CallbackMap.delete(dom); } }; const isUp = (newDisY, disY) => { return newDisY - disY < 0; }; const isDown = (newDisY, disY) => { return newDisY - disY > 0; }; const isLeft = (newDisX, disX) => { return newDisX - disX < 0; }; const isRight = (newDisX, disX) => { return newDisX - disX > 0; }; const moveDefalutElement = (e, actions, options) => { const { width, height, top, left, topStyle = {}, leftStyle = {}, bottomStyle = {}, rightStyle = {} } = options || {}; const moveDisX = e.clientX - actions.initX; const moveDisY = e.clientY - actions.initY; const w = width.value || 0; const h = height.value || 0; const t = top.value || 0; const l = left.value || 0; if (actions.type === "default") { top.value = t + moveDisY; left.value = l + moveDisX; actions.initX = e.clientX; actions.initY = e.clientY; } else { if (isUp(e.clientY, actions.initY) && (actions.type === "top" || actions.type === "bottom")) { console.log("direction isUp"); if (actions.type === "top") { height.value = h - moveDisY; top.value = t + moveDisY; } if (actions.type === "bottom") { height.value = h + moveDisY; } actions.initY = e.clientY; } if (isDown(e.clientY, actions.initY) && (actions.type === "top" || actions.type === "bottom")) { console.log("direction isDown"); if (actions.type === "top") { height.value = h - moveDisY; top.value = t + moveDisY; } if (actions.type === "bottom") { height.value = h + moveDisY; } actions.initY = e.clientY; } if (isLeft(e.clientX, actions.initX) && (actions.type === "left" || actions.type === "right")) { console.log("direction isLeft"); if (actions.type === "left") { width.value = w - moveDisX; left.value = l + moveDisX; } if (actions.type === "right") { width.value = w + moveDisX; } actions.initX = e.clientX; } if (isRight(e.clientX, actions.initX) && (actions.type === "left" || actions.type === "right")) { console.log("direction isRight"); if (actions.type === "left") { width.value = w - moveDisX; left.value = l + moveDisX; } if (actions.type === "right") { width.value = w + moveDisX; } actions.initX = e.clientX; } } }; const initActions = (actions) => { actions.initX = 0; actions.initY = 0; actions.state = ""; actions.type = ""; }; const moveDraggableElement = (type, list, topList, draggableIndex, draggableType) => { if (type === "top" && draggableType.value !== type) { const ele = list[draggableIndex.value]; if (draggableIndex.value !== -1) { ele.position = type; list.splice(draggableIndex.value, 1); topList.push(ele); draggableIndex.value = -1; } } if (type === "bottom" && draggableType.value !== type) { const ele = topList[draggableIndex.value]; if (draggableIndex.value !== -1) { ele.position = type; topList.splice(draggableIndex.value, 1); list.push(ele); draggableIndex.value = -1; } } }; function mitt(n) { return { all: n = n || /* @__PURE__ */ new Map(), on: function(t, e) { var i = n.get(t); i ? i.push(e) : n.set(t, [e]); }, off: function(t, e) { var i = n.get(t); i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : n.set(t, [])); }, emit: function(t, e) { var i = n.get(t); i && i.slice().map(function(n2) { n2(e); }), (i = n.get("*")) && i.slice().map(function(n2) { n2(t, e); }); } }; } let emitter = null; const EventBus = () => { if (emitter) { return emitter; } return emitter = mitt(); }; const _hoisted_1 = ["onDragstart", "draggable"]; const _hoisted_2 = ["onDragstart", "draggable"]; const _sfc_main$1 = /* @__PURE__ */ defineComponent({ __name: "index", props: { childNum: { default: 4 }, squareBottomIndex: { default: 10 }, squareContentIndex: { default: 10 }, squareBottomHeight: { default: 200 }, mainContainerStyle: { default: { height: 600, width: 1e3, zIndex: 10 } }, childList: {} }, emits: ["dragType"], setup(__props, { emit: __emit }) { const emmiter = EventBus(); const props = __props; let defalutSquareBottomHeight = ref(props.squareBottomHeight); const comSquareBottomHeight = computed(() => { const height = defalutSquareBottomHeight.value; if (typeof height === "string") { if (height.includes("%") || height.includes("vh")) { const num = height.replace("vh", "").replace("%", ""); return windowHeight * (Number(num) / 100); } else { return 200; } } else { return Number(props.squareBottomHeight); } }); const list = reactive([]); const topList = reactive([]); const topSquareRef = ref(null); const bottomSquareRef = ref(null); const mainHeight = computed(() => { return props.mainContainerStyle.height - comSquareBottomHeight.value; }); function init() { for (let i = 0; i < props.childNum; i++) { list[i] = { key: "square-bottom" + (i + 1), name: "childSlot" + (i + 1) }; } if (props == null ? void 0 : props.childList) { list.forEach((lObj, i) => { list[i].position = "bottom"; const others = props.childList[i] || {}; list[i] = { ...lObj, ...others }; }); } } init(); const bottomDraggable = ref(true); const topDraggable = ref(true); const draggableIndex = ref(-1); const draggableType = ref(""); const draggableKey = ref("-1"); emmiter.on("clickContainer", (key) => { console.log("key ", key); draggableKey.value = key; }); emmiter.on("mouseEnter", (state) => { topDraggable.value = !state; }); const emits = __emit; const sqaureDragStart = (type, _, i) => { draggableIndex.value = i; draggableType.value = type; }; const sqaureDragEnter = (type) => { moveDraggableElement(type, list, topList, draggableIndex, draggableType); emits("dragType", { type, i: draggableIndex.value, key: draggableKey.value }); }; return (_ctx, _cache) => { var _a, _b, _c, _d; return openBlock(), createElementBlock("div", { class: "main-container", style: normalizeStyle({ height: ((_a = _ctx.mainContainerStyle) == null ? void 0 : _a.height) + "px", width: ((_b = _ctx.mainContainerStyle) == null ? void 0 : _b.width) ? ((_c = _ctx.mainContainerStyle) == null ? void 0 : _c.width) + "px" : "100%", zIndex: (_d = _ctx.mainContainerStyle) == null ? void 0 : _d.zIndex }) }, [ createElementVNode("div", { class: "square-content", ref_key: "topSquareRef", ref: topSquareRef, onDragenter: _cache[0] || (_cache[0] = (e) => { sqaureDragEnter("top"); }), style: normalizeStyle({ height: mainHeight.value + "px", zIndex: _ctx.squareContentIndex }) }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(topList, (child, i) => { return openBlock(), createElementBlock("div", { key: child.key, onDragstart: (e) => { sqaureDragStart("top", e, i); }, draggable: topDraggable.value }, [ renderSlot(_ctx.$slots, child.name, { data: child }, void 0, true) ], 40, _hoisted_1); }), 128)) ], 36), createElementVNode("div", { class: "square-bottom", style: normalizeStyle({ height: comSquareBottomHeight.value + "px", zIndex: _ctx.squareBottomIndex }), ref_key: "bottomSquareRef", ref: bottomSquareRef, onDragenter: _cache[1] || (_cache[1] = (e) => { sqaureDragEnter("bottom"); }) }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(list, (child, i) => { return openBlock(), createElementBlock("div", { key: child.key, onDragstart: (e) => { sqaureDragStart("bottom", e, i); }, draggable: bottomDraggable.value }, [ renderSlot(_ctx.$slots, child.name, { data: child }, void 0, true) ], 40, _hoisted_2); }), 128)) ], 36) ], 4); }; } }); const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const ADraggableMain = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-b6f4cdc8"]]); const showOptions = { showLeft: true, showRight: true, showTop: true, showBottom: true, showTopLeft: false, showTopRight: false, showBottomLeft: false, showBottomRight: false }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "index", props: /* @__PURE__ */ mergeDefaults({ showLeft: { type: Boolean }, showRight: { type: Boolean }, showTop: { type: Boolean }, showBottom: { type: Boolean }, showTopLeft: { type: Boolean }, showTopRight: { type: Boolean }, showBottomLeft: { type: Boolean }, showBottomRight: { type: Boolean }, componentStyle: {}, topStyle: {}, leftStyle: {}, bottomStyle: {}, rightStyle: {}, height: {}, width: {}, top: {}, left: {}, labelKey: {}, canDragSquare: { type: Boolean }, containerIndex: {} }, { labelKey: "-1", containerIndex: 11, canDragSquare: false, ...showOptions }), setup(__props) { const emmiter = EventBus(); const props = __props; const publicStyleAttrs = { zIndex: props.containerIndex + 100 }; const topStyleAttrs = props.topStyle ? { ...props.topStyle, ...publicStyleAttrs } : { ...publicStyleAttrs }; const leftStyleAttrs = props.leftStyle ? { ...props.leftStyle, ...publicStyleAttrs } : { ...publicStyleAttrs }; const bottomStyleAttrs = props.bottomStyle ? { ...props.bottomStyle, ...publicStyleAttrs } : { ...publicStyleAttrs }; const rightStyleAttrs = props.rightStyle ? { ...props.rightStyle, ...publicStyleAttrs } : { ...publicStyleAttrs }; const componentStyle = props.componentStyle || {}; const cWidth = Number((componentStyle.width || "0").replace("px", "")); const cHeight = Number((componentStyle.height || "0").replace("px", "")); const cTop = Number((componentStyle.top || "0").replace("px", "")); const cLeft = Number((componentStyle.left || "0").replace("px", "")); const width = ref(props.width || cWidth || 200); const height = ref(props.height || cHeight || 200); const top = ref(props.top || cTop || 0); const left = ref(props.left || cLeft || 0); const leftRef = ref(null); const rightRef = ref(null); const topRef = ref(null); const bottomRef = ref(null); const defaultRef = ref(null); const actions = reactive({ type: "", // 触发的边框状态 left right top down initX: 0, initY: 0, state: "", mousedownFn: (e) => { actions.state = "down"; actions.initX = e.clientX; actions.initY = e.clientY; }, mouseupFn: (e) => { actions.state = "up"; moveDefalutElement(e, actions, { width, height, top, left }); initActions(actions); } }); const defaultActions = { mousedownFn: (e) => { if (actions.state === "") { actions.type = "default"; actions.state = "default-down"; actions.initX = e.clientX; actions.initY = e.clientY; } }, mouseupFn: (e) => { if (actions.state === "default-down") { actions.type = "default"; actions.state = "default-up"; moveDefalutElement(e, actions, { width, height, top, left }); } initActions(actions); } }; const documentActions = { mousemoveFn: (e) => { if (actions.state === "down") { moveDefalutElement(e, actions, { width, height, top, left, topStyle: props.topStyle, leftStyle: props.leftStyle, bottomStyle: props.bottomStyle, rightStyle: props.rightStyle }); } if (actions.state === "default-down") { moveDefalutElement(e, actions, { width, height, top, left, topStyle: props.topStyle, leftStyle: props.leftStyle, bottomStyle: props.bottomStyle, rightStyle: props.rightStyle }); } } }; const mouseEventFn = (type, state) => { emmiter.emit("mouseEnter", state); actions.type = type; if (state === false) { actions.state = ""; } }; const addDomListener = () => { mouseAddListener(document, documentActions); (props == null ? void 0 : props.showLeft) && mouseAddListener(leftRef.value, actions); (props == null ? void 0 : props.showRight) && mouseAddListener(rightRef.value, actions); (props == null ? void 0 : props.showTop) && mouseAddListener(topRef.value, actions); (props == null ? void 0 : props.showBottom) && mouseAddListener(bottomRef.value, actions); (props == null ? void 0 : props.canDragSquare) && mouseAddListener(defaultRef.value, defaultActions); }; const removeDomListener = () => { mouseRemoveListener(document); mouseRemoveListener(leftRef.value); mouseRemoveListener(rightRef.value); mouseRemoveListener(topRef.value); mouseRemoveListener(bottomRef.value); if (props.canDragSquare) { mouseRemoveListener(defaultRef.value); } }; const init = () => { onMounted(() => { addDomListener(); }); onUnmounted(() => { removeDomListener(); }); }; init(); const clickContainer = () => { emmiter.emit("clickContainer", props.labelKey); }; return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { class: "margin-label-container", style: normalizeStyle({ zIndex: _ctx.containerIndex, ...props.componentStyle || {}, ...width.value && { width: width.value + "px" }, ...height.value && { height: height.value + "px" }, ...top.value && { top: top.value + "px" }, ...left.value && { left: left.value + "px" } }), ref_key: "defaultRef", ref: defaultRef, onMouseenter: clickContainer }, [ _ctx.showTop ? (openBlock(), createElementBlock("div", { key: 0, class: "top separator separator-horizontal", style: normalizeStyle(unref(topStyleAttrs)), onMouseenter: _cache[0] || (_cache[0] = ($event) => mouseEventFn("top", true)), onMouseout: _cache[1] || (_cache[1] = ($event) => mouseEventFn("top", false)), ref_key: "topRef", ref: topRef }, [ !_ctx.topStyle ? (openBlock(), createBlock(unref(_sfc_main$2), { key: 0, name: "arrowRight", color: "#666", iconStyle: { width: "1em", height: "1em" } })) : createCommentVNode("", true) ], 36)) : createCommentVNode("", true), _ctx.showLeft ? (openBlock(), createElementBlock("div", { key: 1, class: "left separator separator-vertical", style: normalizeStyle(unref(leftStyleAttrs)), onMouseenter: _cache[2] || (_cache[2] = ($event) => mouseEventFn("left", true)), onMouseout: _cache[3] || (_cache[3] = ($event) => mouseEventFn("left", false)), ref_key: "leftRef", ref: leftRef }, [ !_ctx.leftStyle ? (openBlock(), createBlock(unref(_sfc_main$2), { key: 0, name: "arrowRight", color: "#666", iconStyle: { width: "1em", height: "1em" } })) : createCommentVNode("", true) ], 36)) : createCommentVNode("", true), _ctx.showBottom ? (openBlock(), createElementBlock("div", { key: 2, class: "bottom separator separator-horizontal", style: normalizeStyle(unref(bottomStyleAttrs)), onMouseenter: _cache[4] || (_cache[4] = ($event) => mouseEventFn("bottom", true)), onMouseout: _cache[5] || (_cache[5] = ($event) => mouseEventFn("bottom", false)), ref_key: "bottomRef", ref: bottomRef }, [ !_ctx.bottomStyle ? (openBlock(), createBlock(unref(_sfc_main$2), { key: 0, name: "arrowRight", color: "#666", iconStyle: { width: "1em", height: "1em" } })) : createCommentVNode("", true) ], 36)) : createCommentVNode("", true), _ctx.showRight ? (openBlock(), createElementBlock("div", { key: 3, class: "right separator separator-vertical", style: normalizeStyle(unref(rightStyleAttrs)), onMouseenter: _cache[6] || (_cache[6] = ($event) => mouseEventFn("right", true)), onMouseout: _cache[7] || (_cache[7] = ($event) => mouseEventFn("right", false)), ref_key: "rightRef", ref: rightRef }, [ !_ctx.rightStyle ? (openBlock(), createBlock(unref(_sfc_main$2), { key: 0, name: "arrowRight", color: "#666", iconStyle: { width: "1em", height: "1em" } })) : createCommentVNode("", true) ], 36)) : createCommentVNode("", true), renderSlot(_ctx.$slots, "default", {}, void 0, true) ], 36); }; } }); const MarginLabel = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-c1ddda83"]]); const components = { SvgIcon: _sfc_main$2, ADraggableMain, MarginLabel }; const index = { install(app) { Object.keys(components).forEach((component) => { app.component(component, components[component]); }); } }; export { ADraggableMain, MarginLabel, _sfc_main$2 as SvgIcon, index as default };