1.新增分割面板组件

This commit is contained in:
dingyongya
2022-01-20 13:32:35 +08:00
parent 47c8714896
commit 4934738a32
4 changed files with 246 additions and 89 deletions

View File

@@ -1,6 +1,7 @@
.lay-split-panel{
height: 100%;
display: flex;
position: relative;
.lay-split-panel-item {
height: 100%;
flex-grow: 1;
@@ -15,20 +16,48 @@
height: 100%;
width: 3px;
border: 1px #eeeeee solid;
background-color: #e8e8e8;
background-color: #fafafa;
border-left: none;
border-right: none;
cursor: col-resize;
display: flex;
align-items: center;
&:before{
content: "";
height: 6px;
width: 100%;
border: 2px solid #dcdee2;
border-left: 0;
border-right: 0;
}
}
}
//.lay-split-panel-line:before{
// content: '';
// position: relative;
// height: 100%;
// left: -5px;
// top: -1px;
// width: 3px;
// border: 1px #eeeeee solid;
// cursor: col-resize;
//}
.lay-split-panel-vertical{
flex-direction: column;
position: relative;
.lay-split-panel-item-move{
user-select: none;
pointer-events: none;
cursor: row-resize;
}
.lay-split-panel-line{
display: flex;
justify-content: center;
width: 100%;
height: 3px;
cursor: row-resize;
border: 1px #eeeeee solid;
background-color: #fafafa;
border-top: none;
border-bottom: none;
&:before{
content: "";
height: 100%;
width: 6px;
border: 2px solid #dcdee2;
border-top: none;
border-bottom: none;
}
}
}

View File

@@ -1,8 +1,10 @@
<template>
<div
ref="target"
class="lay-split-panel"
:style="{ cursor: domStatus ? 'col-resize' : '' }"
:class="['lay-split-panel', vertical ? 'lay-split-panel-vertical' : '']"
:style="{
cursor: domStatus ? (!vertical ? 'col-resize' : 'row-resize') : '',
}"
v-on="{ mouseup: mouseup }"
>
<slot></slot>
@@ -10,59 +12,91 @@
</template>
<script setup name="laySplitPanel" lang="ts">
import {
ref,
watch,
provide,
defineProps,
withDefaults,
defineEmits,
onMounted,
} from "vue";
import { ref, watch, provide, defineProps, withDefaults, onMounted } from "vue";
import "./index.less";
// 属性接口定义
export interface LayStepProps {
active?: number;
vertical?: boolean;
minSize?: number;
}
// props初始化数据定义
const props = withDefaults(defineProps<LayStepProps>(), {
active: 0,
vertical: false,
minSize: 50,
});
let domEvent = ref();
let domStatus = ref(false);
let otherDom = ref(0);
const target = ref();
const divSetInterval = (width, event) => {
console.log(width);
const boxLeft = target.value.offsetLeft;
const boxWidth = target.value.offsetWidth;
const prevDom = domEvent.value.target.previousElementSibling;
const nextDom = domEvent.value.target.nextElementSibling;
const timer = setInterval(() => {
const prevDomLeft = domEvent.value.target.previousElementSibling.offsetLeft;
const lineOffsetLeft = domEvent.value.target.offsetLeft;
prevDom.style.width = ((event.layerX - prevDomLeft) / boxWidth) * 100 + "%";
nextDom.style.width =
((boxWidth - boxLeft - event.layerX - 5) / boxWidth) * 100 + "%";
console.log(event.layerX, prevDomLeft);
}, 100);
if (prevDom?.clientWidth === width) {
clearInterval(timer);
}
};
onMounted(() => {
const boxLeft = target.value.offsetLeft;
const boxWidth = target.value.offsetWidth;
const prevDomLeft = domEvent.value.target.previousElementSibling.offsetLeft;
target.value.addEventListener("mousemove", (event: { layerX: any }) => {
if (domStatus.value) {
divSetInterval(event.layerX - prevDomLeft, event);
console.log(event.layerX, prevDomLeft);
}
const boxHeight = target.value.offsetHeight;
window.addEventListener("scroll", (event) => {
console.log(event);
});
target.value.addEventListener(
"mousemove",
(event: { layerX: any; layerY: any }) => {
if (domStatus.value) {
const prevDom = domEvent.value.target.previousElementSibling;
const nextDom = domEvent.value.target.nextElementSibling;
if (!props.vertical) {
const prevDomLeft =
domEvent.value.target.previousElementSibling.offsetLeft;
const prevDomWidth =
domEvent.value.target.previousElementSibling.offsetWidth;
const nextDomWidth =
domEvent.value.target.nextElementSibling.offsetWidth;
const otherWidth = boxWidth - (prevDomWidth + nextDomWidth + 5);
const otherWidthPercentage =
((prevDomWidth + nextDomWidth + 5) / boxWidth) * 100;
if (
event.layerX - prevDomLeft < props.minSize ||
boxWidth - (event.layerX - prevDomLeft) - otherWidth < props.minSize
) {
return false;
}
prevDom.style.width =
((event.layerX - prevDomLeft) / (prevDomWidth + nextDomWidth + 5)) *
otherWidthPercentage +
"%";
nextDom.style.width =
((boxWidth - (event.layerX - prevDomLeft) - otherWidth) /
(prevDomWidth + nextDomWidth + 5)) *
otherWidthPercentage +
"%";
} else {
const prevDomTop =
domEvent.value.target.previousElementSibling.offsetTop;
const prevDomHeight =
domEvent.value.target.previousElementSibling.offsetHeight;
const nextDomHeight =
domEvent.value.target.nextElementSibling.offsetHeight;
const otherHeight = boxHeight - (prevDomHeight + nextDomHeight + 5);
const otherHeightPercentage =
((prevDomHeight + nextDomHeight + 5) / boxHeight) * 100;
if (
event.layerY - prevDomTop < props.minSize ||
boxHeight - (event.layerY - prevDomTop) - otherHeight <
props.minSize
) {
return false;
}
prevDom.style.height =
((event.layerY - prevDomTop) /
(prevDomHeight + nextDomHeight + 5)) *
otherHeightPercentage +
"%";
nextDom.style.height =
((boxHeight - (event.layerY - prevDomTop) - otherHeight) /
(prevDomHeight + nextDomHeight + 5)) *
otherHeightPercentage +
"%";
}
}
}
);
});
const moveChange = (event: any, status: boolean) => {
@@ -74,9 +108,6 @@ const mouseup = () => {
domStatus.value = false;
};
// 绑定事件
const emits = defineEmits(["onChange"]);
// 定义初始化个数数组
const steps = ref([]);
// 监听有几个lay-split-panel-item
@@ -87,6 +118,7 @@ watch(steps, () => {
}
);
});
// 向lay-split-panel-item传递参数
provide("laySplitPanel", {
props,

View File

@@ -2,12 +2,22 @@
<div
v-if="!isStart"
:class="[!isStart ? 'lay-split-panel-line' : '']"
:style="{ cursor: 'col-resize' }"
ref="el"
v-on="{ mousedown: mousedown, mouseup: mouseup }"
></div>
<div :class="['lay-split-panel-item']">
<slot> {{ parents.elementX }}{{ pressed }}</slot>
<div
v-if="isVertical"
:class="['lay-split-panel-item']"
:style="{ height: `${space ? space : (100 + space) / stepsCount}%` }"
>
<slot></slot>
</div>
<div
v-else
:class="['lay-split-panel-item']"
:style="{ width: `${space ? space : (100 + space) / stepsCount}%` }"
>
<slot></slot>
</div>
</template>
@@ -28,19 +38,12 @@ import {
import type { ComputedRef } from "vue";
export interface LayStepItemProps {
title?: string;
content?: string;
icon?: string;
status?: string;
space?: number;
}
const props = withDefaults(defineProps<LayStepItemProps>(), {
title: "",
content: "",
icon: "",
status: "",
space: 0,
});
const index = ref(-1);
const parents: any = inject("laySplitPanel");
const currentInstance: any = getCurrentInstance();
@@ -51,15 +54,10 @@ const setIndex = (val: number) => {
const mousedown = (event: any) => {
moveStatus.value = true;
const prevDomWidth = event.target.previousElementSibling.offsetWidth;
const lineOffsetLeft = event.target.offsetLeft;
parents.moveChange(event, true);
console.log(prevDomWidth);
console.log(lineOffsetLeft);
};
const mouseup = (event: any, index: any) => {
const mouseup = (event: any) => {
moveStatus.value = false;
};
@@ -68,7 +66,7 @@ const stepsCount = computed(() => {
});
const isVertical = computed(() => {
return parents.props.direction === "vertical";
return parents.props.vertical;
});
const isLast: ComputedRef<boolean> = computed(() => {
@@ -80,10 +78,10 @@ const isLast: ComputedRef<boolean> = computed(() => {
const isStart: ComputedRef<boolean> = computed(() => {
return parents.steps.value[0]?.itemId === currentInstance.uid;
});
const stepItemState = reactive({
itemId: computed(() => currentInstance?.uid),
setIndex,
width: [],
});
parents.steps.value = [...parents.steps.value, stepItemState];