import { defineComponent, ref, unref, computed, type PropType } from "vue"; import resizer from "./resizer"; import "./index.css"; export interface ContextProps { minPercent: number; defaultPercent: number; split: string; } /** 切割面板组件 */ export default defineComponent({ name: "SplitPane", components: { resizer }, props: { splitSet: { type: Object as PropType, require: true } }, emits: ["resize"], setup(props, ctx) { const active = ref(false); const hasMoved = ref(false); const percent = ref(props.splitSet?.defaultPercent); const type = props.splitSet?.split === "vertical" ? "width" : "height"; const resizeType = props.splitSet?.split === "vertical" ? "left" : "top"; const leftClass = ref([ "splitter-pane splitter-paneL", props.splitSet?.split ]); const rightClass = ref([ "splitter-pane splitter-paneR", props.splitSet?.split ]); const cursor = computed(() => { return active.value ? props.splitSet?.split === "vertical" ? { cursor: "col-resize" } : { cursor: "row-resize" } : { cursor: "default" }; }); const onClick = (): void => { if (!hasMoved.value) { percent.value = 50; ctx.emit("resize", percent.value); } }; const onMouseDown = (): void => { active.value = true; hasMoved.value = false; }; const onMouseUp = (): void => { active.value = false; }; const onMouseMove = (e: any): void => { if (e.buttons === 0 || e.which === 0) { active.value = false; } if (active.value) { let offset = 0; let target = e.currentTarget; if (props.splitSet?.split === "vertical") { while (target) { offset += target.offsetLeft; target = target.offsetParent; } } else { while (target) { offset += target.offsetTop; target = target.offsetParent; } } const currentPage = props.splitSet?.split === "vertical" ? e.pageX : e.pageY; const targetOffset = props.splitSet?.split === "vertical" ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight; const percents = Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100; if ( percents > props.splitSet?.minPercent && percents < 100 - props.splitSet?.minPercent ) { percent.value = percents; } ctx.emit("resize", percent.value); hasMoved.value = true; } }; return () => ( <>
onMouseUp()} onMousemove={() => onMouseMove(event)} >
{ctx.slots.paneL()}
onMouseDown()} onClick={() => onClick()} >
{ctx.slots.paneR()}
); } });