| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- import "./index.css";
- import resizer from "./resizer";
- import { type PropType, defineComponent, ref, unref, computed } from "vue";
- export interface ContextProps {
- minPercent: number;
- defaultPercent: number;
- split: string;
- }
- /** 切割面板组件 */
- export default defineComponent({
- name: "SplitPane",
- components: { resizer },
- props: {
- splitSet: {
- type: Object as PropType<ContextProps>,
- 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 () => (
- <>
- <div
- class="vue-splitter-container clearfix"
- style={unref(cursor)}
- onMouseup={() => onMouseUp()}
- onMousemove={() => onMouseMove(event)}
- >
- <div
- class={unref(leftClass)}
- style={{ [unref(type)]: unref(percent) + "%" }}
- >
- {ctx.slots.paneL()}
- </div>
- <resizer
- style={`${unref([resizeType])}:${unref(percent)}%`}
- split={props.splitSet?.split}
- onMousedown={() => onMouseDown()}
- onClick={() => onClick()}
- ></resizer>
- <div
- class={unref(rightClass)}
- style={{ [unref(type)]: 100 - unref(percent) + "%" }}
- >
- {ctx.slots.paneR()}
- </div>
- <div v-show={unref(active)} class="vue-splitter-container-mask"></div>
- </div>
- </>
- );
- }
- });
|