fe-drone-ci/src/components/SplitPane/index.vue

112 lines
2.7 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>
<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>
<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>