split-pane-vue3
Version:
239 lines (238 loc) • 9.78 kB
JavaScript
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
};