UNPKG

split-pane-vue3

Version:
239 lines (238 loc) 9.78 kB
import { openBlock as R, createElementBlock as E, normalizeClass as w, createElementVNode as c, renderSlot as M, pushScopeId as T, popScopeId as x } from "vue"; const W = (e, t) => { const i = e.__vccOpts || e; for (const [n, s] of t) i[n] = s; return i; }, H = { // name: "PageSplit", data() { return { resizeLinePaneId: `resize-line-pane-${this.geneRamdId()}`, resizeLineId: `resize-line-${this.geneRamdId()}`, pane1stId: `pane-1st-${this.geneRamdId()}`, pane2ndId: `pane-2nd-${this.geneRamdId()}`, resizeTimeout: null, interval: 500 }; }, props: { // 面板位置,可以是 0~1 代表百分比 distribute: { type: Number, default: 0.5, validator: function(e) { return e > 0 && e < 1; } }, // 调整模式(true:ResizeLine垂直摆放,false:ResizeLine水平摆放) isVertical: { type: Boolean, default: !0 }, // 分割线的宽度 lineThickness: { type: Number, default: 2, validator: function(e) { return e >= 1; } }, // 分割线中是否有三条杠 hasLineTip: { type: Boolean, default: !0 }, // 分割线的背景颜色 backgroundColor: { type: String, default: "#a0cfff" }, // 分割线的鼠标hover后的颜色 hoverColor: { type: String, default: "#409eff" }, // 分割线是否有box-shadow样式 hasBoxShadow: { type: Boolean, default: !0 }, // 左组件/上组件的最小宽度/高度,必须>=0 firstMinValue: { type: Number, default: 0, validator: function(e) { return e >= 0; } }, // 右组件/下组件的最小宽度/高度,必须>=0 secondMinValue: { type: Number, default: 0, validator: function(e) { return e >= 0; } }, // 左组件/上组件是否需要遮挡层(如果组件内有iframe,是需要有遮挡层的,否则鼠标进入iframe区域后,是发送不到鼠标移动事件的) isFirstComponentMasked: { type: Boolean, default: !1 }, // 右组件/下组件是否需要遮挡层(如果组件内有iframe,是需要有遮挡层的,否则鼠标进入iframe区域后,是发送不到鼠标移动事件的) isSecondComponentMasked: { type: Boolean, default: !1 } }, watch: { isVertical: function() { this.init(); }, distribute: function() { this.init(); } }, mounted() { this.init(), window.addEventListener("resize", this.$_eventCallback, !1); }, unmounted() { window.removeEventListener("resize", this.$_eventCallback); }, methods: { init() { const e = document.getElementById(this.resizeLinePaneId), t = document.getElementById(this.resizeLineId), i = document.getElementById(this.pane1stId), n = document.getElementById(this.pane2ndId); if (t.style.backgroundColor = this.backgroundColor, this.hasBoxShadow && (t.style.boxShadow = "0px 0px 1px inset"), this.hasLineTip) { let o = t.getElementsByClassName("tip")[0].getElementsByClassName("line"); for (const k of o) k.style.backgroundColor = this.hoverColor; } let s = this.isVertical ? e.offsetWidth : e.offsetHeight, d = this.lineThickness / s, p = 0, _ = 0; this.firstMinValue > 0 && (p = this.firstMinValue / s), this.secondMinValue > 0 && (_ = this.secondMinValue / s); let y = d / 2, l = this.distribute - y, a = 1 - this.distribute - y; p > l ? (l = p, a = 1 - l - d) : _ > a && (a = _, l = 1 - a - d); let b = l * 100, V = a * 100; this.isVertical ? (i.style.width = b + "%", n.style.width = V + "%", t.style.width = this.lineThickness + "px", i.style.height = null, n.style.height = null, t.style.height = null) : (i.style.height = b + "%", n.style.height = V + "%", t.style.height = this.lineThickness + "px", i.style.width = null, n.style.width = null, t.style.width = null); let v = this.firstMinValue, z = this.secondMinValue, r = this.isVertical, I, g, C; t.onmousedown = (o) => { this.$emit("resizeLineStartMove"); let k, $, L, B; if (s = r ? e.offsetWidth : e.offsetHeight, this.isFirstComponentMasked) { let { maskNode: h, originPosition: u } = this.$_addMask(i); k = h, L = u; } if (this.isSecondComponentMasked) { let { maskNode: h, originPosition: u } = this.$_addMask(n); $ = h, B = u; } return o = o || window.event, I = r ? o.clientX : o.clientY, g = i[r ? "offsetWidth" : "offsetHeight"], C = n[r ? "offsetWidth" : "offsetHeight"], document.onmousemove = (h) => { this.$emit("resizeLineMove", h); let u = r ? h.clientX : h.clientY, m = g + (u - I); if (g === v && m < v) return; let f = C + (I - u); if (C === z && f < z) return; m < v ? (m = v, f = C + (g - m)) : f < z && (f = z, m = g + (C - f)); let P = m / s * 100, N = f / s * 100; i.style[r ? "width" : "height"] = P + "%", n.style[r ? "width" : "height"] = N + "%"; }, document.onmouseup = () => { this.$emit("resizeLineEndMove"), this.isFirstComponentMasked && this.$_removeMask(i, k, L), this.isSecondComponentMasked && this.$_removeMask(n, $, B), document.onmousemove = null, document.onmouseup = null, t.releaseCapture && t.releaseCapture(); }, t.setCapture && t.setCapture(), !1; }, t.onmouseenter = (o) => { this.$_addClass(t, "resize-hover"), o.target.style.backgroundColor = this.hoverColor; }, t.onmouseleave = (o) => { this.$_removeClass(t, "resize-hover"), o.target.style.backgroundColor = this.backgroundColor; }; }, // 当窗口调整大小的时侯,让resizeline的相对位置不变 $_handleWindowResize() { let e = document.getElementById(this.resizeLinePaneId); document.getElementById(this.resizeLineId); const t = document.getElementById(this.pane1stId), i = document.getElementById(this.pane2ndId); let n = this.isVertical ? e.offsetWidth : e.offsetHeight, s = (this.isVertical ? t.style.width : t.style.height).slice(0, -1), d = (this.isVertical ? i.style.width : i.style.height).slice(0, -1), p = 100 - s - d, y = this.lineThickness / n * 100 - p, l = s - y / 2, a = d - y / 2; this.isVertical ? (t.style.width = l + "%", i.style.width = a + "%") : (t.style.height = l + "%", i.style.height = a + "%"); }, $_addClass(e, t) { e.className.indexOf(t) < 0 && (e.className = e.className + " " + t); }, $_removeClass(e, t) { e.className = e.className.replace(t, "").trim(); }, /** * @description 为左右/上下组件添加一个遮挡层 * @param {Dom} parentNode 需要放置遮挡层的节点,一般就是上面的firstComponent、secondComponent * @returns {Object} 结构如下: * { * mask: 遮挡层节点(一般就是一个div) * originPosition:parentNode的position的原来的值,记下这个值是因为本方法会将parentNode的position改为relative * } */ $_addMask(e) { let t = e.style.position; e.style.position = "relative"; let i = document.createElement("div"); return i.style.backgroundColor = "transparent", i.style.position = "absolute", i.style.width = "100%", i.style.height = "100%", i.style.top = "0", i.style.left = "0", e.appendChild(i), { maskNode: i, originPosition: t }; }, /** * @description 从左右/上下组件删除一个遮挡层 * @param {Dom} parentNode 需要放置遮挡层的节点,一般就是上面的firstComponent、secondComponent * @param {Dom} maskNode 遮挡层节点(一般就是一个div) * @param {String} originPositionOfParendNode parentNode的position的原来的值 */ $_removeMask(e, t, i) { e.removeChild(t), e.style.position = i; }, /** * 如果用原生的resize事件,将会损耗大量资源,因为resize事件触发的次数非常多 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Window/resize_event#settimeout */ $_eventCallback() { this.resizeTimeout || (this.resizeTimeout = setTimeout(() => { this.resizeTimeout = null, this.$_handleWindowResize(); }, this.interval)); }, geneRamdId() { return Number.parseInt(Math.random() * 1e5); } } }, S = (e) => (T("data-v-b8b77c6f"), e = e(), x(), e), O = ["id"], F = ["id"], X = ["id"], Y = /* @__PURE__ */ S(() => /* @__PURE__ */ c("div", { class: "line" }, null, -1)), j = /* @__PURE__ */ S(() => /* @__PURE__ */ c("div", { class: "line" }, null, -1)), q = /* @__PURE__ */ S(() => /* @__PURE__ */ c("div", { class: "line" }, null, -1)), A = [ Y, j, q ], D = ["id"]; function G(e, t, i, n, s, d) { return R(), E("div", { id: s.resizeLinePaneId, class: w(["resize-line-pane", i.isVertical ? "pane-vertical" : "pane-horizontal"]) }, [ c("div", { id: s.pane1stId, class: "pane pane-1st" }, [ M(e.$slots, "first", {}, void 0, !0) ], 8, F), c("div", { id: s.resizeLineId, class: w(["resize-line", i.isVertical ? "resize-vertical" : "resize-horizontal"]) }, [ c("div", { class: w(["tip", i.isVertical ? "vertical" : "horizontal"]) }, A, 2) ], 10, X), c("div", { id: s.pane2ndId, class: "pane pane-2nd" }, [ M(e.$slots, "second", {}, void 0, !0) ], 8, D), M(e.$slots, "default", {}, void 0, !0) ], 10, O); } const K = /* @__PURE__ */ W(H, [["render", G], ["__scopeId", "data-v-b8b77c6f"]]); export { K as default };