1.新增分割面板组件
This commit is contained in:
parent
47c8714896
commit
4934738a32
@ -10,31 +10,129 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<lay-split-panel style="height: 300px">
|
<lay-split-panel style="height: 300px">
|
||||||
<lay-split-panel-item>1</lay-split-panel-item>
|
<lay-split-panel-item>A</lay-split-panel-item>
|
||||||
<lay-split-panel-item>2</lay-split-panel-item>
|
<lay-split-panel-item>B</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item>C</lay-split-panel-item>
|
||||||
</lay-split-panel>
|
</lay-split-panel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const loading = ref(true);
|
|
||||||
const active = ref(-1);
|
|
||||||
const nexts = () => {
|
|
||||||
if (active.value++ >=3) active.value = 0
|
|
||||||
};
|
|
||||||
const previous = () => {
|
|
||||||
if (active.value-- ===0) active.value = 0
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
loading,
|
|
||||||
active
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
::: title 自定义比例
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
::: demo
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<lay-split-panel style="height: 300px">
|
||||||
|
<lay-split-panel-item :space="30">1</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item :space="20">2</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item :space="50">3</lay-split-panel-item>
|
||||||
|
</lay-split-panel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title 垂直布局
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
::: demo
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<lay-split-panel :vertical="true" style="height: 600px; width: 100%">
|
||||||
|
<lay-split-panel-item>1</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item>2</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item>3</lay-split-panel-item>
|
||||||
|
</lay-split-panel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title 组合用法
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
::: demo
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<lay-split-panel style="height: 600px;">
|
||||||
|
<lay-split-panel-item :space="60">
|
||||||
|
<lay-split-panel :vertical="true" style="height: 600px; width: 100%">
|
||||||
|
<lay-split-panel-item :space="40">1</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item :space="40">2</lay-split-panel-item>
|
||||||
|
</lay-split-panel>
|
||||||
|
</lay-split-panel-item>
|
||||||
|
<lay-split-panel-item :space="40">2</lay-split-panel-item>
|
||||||
|
</lay-split-panel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title splitPanel属性
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: table
|
||||||
|
|
||||||
|
| 属性 | 描述 | 类型 |可选值 | 默认值|
|
||||||
|
| ----- | ---- | ------ | ---| ---|
|
||||||
|
| vertical | 是否垂直布局 | Boolean |`true` `false`| false |
|
||||||
|
| minSize | 块拉动最小范围(按像素 `px`) | number | - | 50 |
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: title splitPanelItem属性
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: table
|
||||||
|
|
||||||
|
| 属性 | 描述 | 类型 |可选值 | 默认值|
|
||||||
|
| ----- | ---- | ------ | ---| ---|
|
||||||
|
| space | 默认每个站多大比例(`%`), 设置一个,<br/> 其他的都需要设置,合计为(`100` ) | number | - | 按照个数平分 |
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
::: comment
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: previousNext splitPanel
|
||||||
|
:::
|
@ -1,6 +1,7 @@
|
|||||||
.lay-split-panel{
|
.lay-split-panel{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
.lay-split-panel-item {
|
.lay-split-panel-item {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -15,20 +16,48 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
border: 1px #eeeeee solid;
|
border: 1px #eeeeee solid;
|
||||||
background-color: #e8e8e8;
|
background-color: #fafafa;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
cursor: col-resize;
|
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-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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//.lay-split-panel-line:before{
|
|
||||||
// content: '';
|
|
||||||
// position: relative;
|
|
||||||
// height: 100%;
|
|
||||||
// left: -5px;
|
|
||||||
// top: -1px;
|
|
||||||
// width: 3px;
|
|
||||||
// border: 1px #eeeeee solid;
|
|
||||||
// cursor: col-resize;
|
|
||||||
//}
|
|
||||||
}
|
}
|
@ -1,8 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="target"
|
ref="target"
|
||||||
class="lay-split-panel"
|
:class="['lay-split-panel', vertical ? 'lay-split-panel-vertical' : '']"
|
||||||
:style="{ cursor: domStatus ? 'col-resize' : '' }"
|
:style="{
|
||||||
|
cursor: domStatus ? (!vertical ? 'col-resize' : 'row-resize') : '',
|
||||||
|
}"
|
||||||
v-on="{ mouseup: mouseup }"
|
v-on="{ mouseup: mouseup }"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
@ -10,59 +12,91 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="laySplitPanel" lang="ts">
|
<script setup name="laySplitPanel" lang="ts">
|
||||||
import {
|
import { ref, watch, provide, defineProps, withDefaults, onMounted } from "vue";
|
||||||
ref,
|
|
||||||
watch,
|
|
||||||
provide,
|
|
||||||
defineProps,
|
|
||||||
withDefaults,
|
|
||||||
defineEmits,
|
|
||||||
onMounted,
|
|
||||||
} from "vue";
|
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
// 属性接口定义
|
// 属性接口定义
|
||||||
export interface LayStepProps {
|
export interface LayStepProps {
|
||||||
active?: number;
|
vertical?: boolean;
|
||||||
|
minSize?: number;
|
||||||
}
|
}
|
||||||
// props初始化数据定义
|
// props初始化数据定义
|
||||||
const props = withDefaults(defineProps<LayStepProps>(), {
|
const props = withDefaults(defineProps<LayStepProps>(), {
|
||||||
active: 0,
|
vertical: false,
|
||||||
|
minSize: 50,
|
||||||
});
|
});
|
||||||
let domEvent = ref();
|
let domEvent = ref();
|
||||||
let domStatus = ref(false);
|
let domStatus = ref(false);
|
||||||
let otherDom = ref(0);
|
|
||||||
const target = ref();
|
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(() => {
|
onMounted(() => {
|
||||||
const boxLeft = target.value.offsetLeft;
|
|
||||||
const boxWidth = target.value.offsetWidth;
|
const boxWidth = target.value.offsetWidth;
|
||||||
const prevDomLeft = domEvent.value.target.previousElementSibling.offsetLeft;
|
const boxHeight = target.value.offsetHeight;
|
||||||
target.value.addEventListener("mousemove", (event: { layerX: any }) => {
|
window.addEventListener("scroll", (event) => {
|
||||||
if (domStatus.value) {
|
console.log(event);
|
||||||
divSetInterval(event.layerX - prevDomLeft, event);
|
|
||||||
console.log(event.layerX, prevDomLeft);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
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) => {
|
const moveChange = (event: any, status: boolean) => {
|
||||||
@ -74,9 +108,6 @@ const mouseup = () => {
|
|||||||
domStatus.value = false;
|
domStatus.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 绑定事件
|
|
||||||
const emits = defineEmits(["onChange"]);
|
|
||||||
|
|
||||||
// 定义初始化个数数组
|
// 定义初始化个数数组
|
||||||
const steps = ref([]);
|
const steps = ref([]);
|
||||||
// 监听有几个lay-split-panel-item
|
// 监听有几个lay-split-panel-item
|
||||||
@ -87,6 +118,7 @@ watch(steps, () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 向lay-split-panel-item传递参数
|
// 向lay-split-panel-item传递参数
|
||||||
provide("laySplitPanel", {
|
provide("laySplitPanel", {
|
||||||
props,
|
props,
|
||||||
|
@ -2,12 +2,22 @@
|
|||||||
<div
|
<div
|
||||||
v-if="!isStart"
|
v-if="!isStart"
|
||||||
:class="[!isStart ? 'lay-split-panel-line' : '']"
|
:class="[!isStart ? 'lay-split-panel-line' : '']"
|
||||||
:style="{ cursor: 'col-resize' }"
|
|
||||||
ref="el"
|
ref="el"
|
||||||
v-on="{ mousedown: mousedown, mouseup: mouseup }"
|
v-on="{ mousedown: mousedown, mouseup: mouseup }"
|
||||||
></div>
|
></div>
|
||||||
<div :class="['lay-split-panel-item']">
|
<div
|
||||||
<slot> {{ parents.elementX }}{{ pressed }}</slot>
|
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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -28,19 +38,12 @@ import {
|
|||||||
import type { ComputedRef } from "vue";
|
import type { ComputedRef } from "vue";
|
||||||
|
|
||||||
export interface LayStepItemProps {
|
export interface LayStepItemProps {
|
||||||
title?: string;
|
space?: number;
|
||||||
content?: string;
|
|
||||||
icon?: string;
|
|
||||||
status?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<LayStepItemProps>(), {
|
const props = withDefaults(defineProps<LayStepItemProps>(), {
|
||||||
title: "",
|
space: 0,
|
||||||
content: "",
|
|
||||||
icon: "",
|
|
||||||
status: "",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const index = ref(-1);
|
const index = ref(-1);
|
||||||
const parents: any = inject("laySplitPanel");
|
const parents: any = inject("laySplitPanel");
|
||||||
const currentInstance: any = getCurrentInstance();
|
const currentInstance: any = getCurrentInstance();
|
||||||
@ -51,15 +54,10 @@ const setIndex = (val: number) => {
|
|||||||
|
|
||||||
const mousedown = (event: any) => {
|
const mousedown = (event: any) => {
|
||||||
moveStatus.value = true;
|
moveStatus.value = true;
|
||||||
const prevDomWidth = event.target.previousElementSibling.offsetWidth;
|
|
||||||
const lineOffsetLeft = event.target.offsetLeft;
|
|
||||||
parents.moveChange(event, true);
|
parents.moveChange(event, true);
|
||||||
|
|
||||||
console.log(prevDomWidth);
|
|
||||||
console.log(lineOffsetLeft);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mouseup = (event: any, index: any) => {
|
const mouseup = (event: any) => {
|
||||||
moveStatus.value = false;
|
moveStatus.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,7 +66,7 @@ const stepsCount = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const isVertical = computed(() => {
|
const isVertical = computed(() => {
|
||||||
return parents.props.direction === "vertical";
|
return parents.props.vertical;
|
||||||
});
|
});
|
||||||
|
|
||||||
const isLast: ComputedRef<boolean> = computed(() => {
|
const isLast: ComputedRef<boolean> = computed(() => {
|
||||||
@ -80,10 +78,10 @@ const isLast: ComputedRef<boolean> = computed(() => {
|
|||||||
const isStart: ComputedRef<boolean> = computed(() => {
|
const isStart: ComputedRef<boolean> = computed(() => {
|
||||||
return parents.steps.value[0]?.itemId === currentInstance.uid;
|
return parents.steps.value[0]?.itemId === currentInstance.uid;
|
||||||
});
|
});
|
||||||
|
|
||||||
const stepItemState = reactive({
|
const stepItemState = reactive({
|
||||||
itemId: computed(() => currentInstance?.uid),
|
itemId: computed(() => currentInstance?.uid),
|
||||||
setIndex,
|
setIndex,
|
||||||
|
width: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
parents.steps.value = [...parents.steps.value, stepItemState];
|
parents.steps.value = [...parents.steps.value, stepItemState];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user