赞
踩
目录
参考文章:封装vue通用拖拽滑动分隔面板组件(Split) - 掘金
使用js库:splitpanes https://antoniandre.github.io/splitpanes/https://antoniandre.github.io/splitpanes/
使用方法:
npm i splitpanes # For Vue 3
完整代码:
- <template>
- <div ref="splitPane" class="split-pane" :class="props.direction" :style="{ flexDirection: direction }">
- <div class="pane pane-one" :style="lengthType + ':' + paneLengthValue">
- <slot name="one"></slot>
- </div>
- <div class="pane-trigger" :style="lengthType + ':' + triggerLengthValue" @mousedown="handleMouseDown"></div>
- <div class="pane pane-two">
- <slot name="two"></slot>
- </div>
- </div>
- </template>
-
- <script setup>
- import { ref, defineProps, computed } from 'vue'
- /* 属性 */
- const splitPane = ref()
- let paneLengthPercent = ref(50) // 区域1宽度 (%)
- let triggerLength = ref(10) // 滑动器宽度 (px)
- let triggerLeftOffset = ref(0) // 鼠标距滑动器左(顶)侧偏移量
- const props = defineProps({
- direction: {
- type: String,
- default: 'column'
- },
- //滑动限制-最小
- min: {
- type: Number,
- default: 10
- },
- //滑动限制-最大
- max: {
- type: Number,
- default: 90
- },
- paneLengthPercent: {
- type: Number,
- default: 50
- },
-
- triggerLength: {
- type: Number,
- default: 10
- }
-
- })
- const lengthType = computed(() => {
- return props.direction === 'row' ? 'width' : 'height'
- })
- const paneLengthValue = computed(() => {
- return `calc(${paneLengthPercent.value}% - ${triggerLength.value / 2 + 'px'})`
- })
- const triggerLengthValue = computed(() => {
- return triggerLength.value + 'px'
- })
-
- /* 方法 */
- // 按下滑动器
- const handleMouseDown = (e) => {
- document.addEventListener('mousemove', handleMouseMove)
- document.addEventListener('mouseup', handleMouseUp)
- if (props.direction === 'row') {
- triggerLeftOffset.value = e.pageX - e.srcElement.getBoundingClientRect().left
- } else {
- triggerLeftOffset.value = e.pageY - e.srcElement.getBoundingClientRect().top
- }
-
- }
-
- // 按下滑动器后移动鼠标
- const handleMouseMove = (e) => {
- const clientRect = splitPane.value.getBoundingClientRect()
- paneLengthPercent.value = 0
- //方向判断
- if (props.direction === 'row') {
- const offset = e.pageX - clientRect.left - triggerLeftOffset.value + triggerLength.value / 2
- paneLengthPercent.value = (offset / clientRect.width) * 100
- } else {
- const offset = e.pageY - clientRect.top - triggerLeftOffset.value + triggerLength.value / 2
- paneLengthPercent.value = (offset / clientRect.height) * 100
- }
- //滑动限制判断
- if (paneLengthPercent.value < props.min) {
- paneLengthPercent.value = props.min
- }
- if (paneLengthPercent.value > props.max) {
- paneLengthPercent.value = props.max
- }
-
- }
-
- // 松开滑动器
- const handleMouseUp = () => {
- document.removeEventListener('mousemove', handleMouseMove)
- }
-
- </script>
-
- <style scoped lang="scss">
- .split-pane {
- background: palegreen;
- height: 100%;
- display: flex;
-
- &.row {
- .pane {
- height: 100%;
- }
-
- .pane-trigger {
- height: 100%;
- cursor: col-resize; //鼠标样式
- }
- }
-
- &.column {
- .pane {
- width: 100%;
-
- }
-
- .pane-trigger {
- width: 100%;
- cursor: row-resize; //鼠标样式
- }
- }
-
- .pane-one {
- width: 50%;
- background: palevioletred;
- }
-
- .pane-trigger {
- background: palegoldenrod;
- user-select: none;
- }
-
- .pane-two {
- flex: 1;
- background: turquoise;
- }
- }
- </style>
参考文章:Vue中 引入使用 vue-splitpane 实现窗格的拆分、调节_明天也要努力的博客-CSDN博客_vue-splitpane
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。