111 lines
3.2 KiB
Vue
111 lines
3.2 KiB
Vue
<template>
|
|
<div ref :style="{ cursor, userSelect}" class="vue-splitter-container clearfix" @mouseup="onMouseUp"
|
|
@mousemove="onMouseMove">
|
|
<Pane class="splitter-pane splitter-paneL" :split="split" :style="{ [type]: percent+'%'}">
|
|
<slot name="paneL"></slot>
|
|
</Pane>
|
|
<Resizer :style="{ [resizeType]: percent+'%'}" :split="split" :onMouseDown="onMouseDown"
|
|
@click="onClick"></Resizer>
|
|
<Pane class="splitter-pane splitter-paneR" :split="split" :style="{ [type]: 100-percent+'%'}">
|
|
<slot name="paneR"></slot>
|
|
</Pane>
|
|
</div>
|
|
</template>
|
|
<style scoped>
|
|
.clearfix:after {
|
|
visibility: hidden;
|
|
display: block;
|
|
font-size: 0;
|
|
content: " ";
|
|
clear: both;
|
|
height: 0;
|
|
}
|
|
.vue-splitter-container {
|
|
height: 100%;
|
|
/*display: flex;*/
|
|
position: relative;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import Resizer from './Resizer';
|
|
import Pane from './Pane';
|
|
export default {
|
|
name: 'splitPane',
|
|
components: { Resizer, Pane },
|
|
props: {
|
|
margin: {
|
|
type: Number,
|
|
default: 10
|
|
},
|
|
split: {
|
|
validator(value) {
|
|
return ['vertical', 'horizontal'].indexOf(value) >= 0
|
|
},
|
|
required: true
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
active: false,
|
|
hasMoved: false,
|
|
height: null,
|
|
percent: 50,
|
|
type: this.split === 'vertical' ? 'width' : 'height',
|
|
resizeType: this.split === 'vertical' ? 'left' : 'top'
|
|
}
|
|
},
|
|
computed: {
|
|
userSelect() {
|
|
return this.active ? 'none' : ''
|
|
},
|
|
cursor() {
|
|
return this.active ? 'col-resize' : ''
|
|
}
|
|
},
|
|
methods: {
|
|
onClick() {
|
|
if (!this.hasMoved) {
|
|
this.percent = 50;
|
|
this.$emit('resize');
|
|
}
|
|
},
|
|
onMouseDown() {
|
|
this.active = true;
|
|
this.hasMoved = false;
|
|
},
|
|
onMouseUp() {
|
|
this.active = false;
|
|
},
|
|
onMouseMove(e) {
|
|
if (e.buttons === 0 || e.which === 0) {
|
|
this.active = false;
|
|
}
|
|
if (this.active) {
|
|
let offset = 0;
|
|
let target = e.currentTarget;
|
|
if (this.split === 'vertical') {
|
|
while (target) {
|
|
offset += target.offsetLeft;
|
|
target = target.offsetParent;
|
|
}
|
|
} else {
|
|
while (target) {
|
|
offset += target.offsetTop;
|
|
target = target.offsetParent;
|
|
}
|
|
}
|
|
|
|
const currentPage = this.split === 'vertical' ? e.pageX : e.pageY;
|
|
const targetOffset = this.split === 'vertical' ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight;
|
|
const percent = Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100;
|
|
if (percent > this.margin && percent < 100 - this.margin) {
|
|
this.percent = percent;
|
|
}
|
|
this.$emit('resize');
|
|
this.hasMoved = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|