增加组件splitPane
This commit is contained in:
parent
6955d75dd6
commit
effde49ba7
4
index.js
4
index.js
@ -4,6 +4,7 @@ import Pagination from './src/components/Pagination/index.vue'
|
|||||||
import BaseTable from './src/components/BaseTable/index.vue'
|
import BaseTable from './src/components/BaseTable/index.vue'
|
||||||
import InputArea from './src/components/BaseTable/subcomponents/InputArea.vue'
|
import InputArea from './src/components/BaseTable/subcomponents/InputArea.vue'
|
||||||
import MethodBtn from './src/components/BaseTable/subcomponents/MethodBtn.vue'
|
import MethodBtn from './src/components/BaseTable/subcomponents/MethodBtn.vue'
|
||||||
|
import SplitPane from './src/components/SplitPane/index.vue'
|
||||||
|
|
||||||
let ModuleObj = {
|
let ModuleObj = {
|
||||||
SearchBar,
|
SearchBar,
|
||||||
@ -11,7 +12,8 @@ let ModuleObj = {
|
|||||||
Pagination,
|
Pagination,
|
||||||
BaseTable,
|
BaseTable,
|
||||||
InputArea,
|
InputArea,
|
||||||
MethodBtn
|
MethodBtn,
|
||||||
|
SplitPane
|
||||||
}
|
}
|
||||||
let MyModule = {}
|
let MyModule = {}
|
||||||
MyModule.install = (Vue) => {
|
MyModule.install = (Vue) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "code-brick-zj",
|
"name": "code-brick-zj",
|
||||||
"version": "0.0.7",
|
"version": "0.1.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "组件封装",
|
"description": "组件封装",
|
||||||
"main": "index.js"
|
"main": "index.js"
|
||||||
|
334
src/components/SplitPane/index.vue
Normal file
334
src/components/SplitPane/index.vue
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="outerWrapper" :class="wrapperClasses">
|
||||||
|
<div v-if="isHorizontal" :class="`${prefix}-horizontal`">
|
||||||
|
<div
|
||||||
|
:style="{ right: `${anotherOffset}%` }"
|
||||||
|
class="left-pane"
|
||||||
|
:class="paneClasses"
|
||||||
|
>
|
||||||
|
<slot name="left" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="`${prefix}-trigger-con`"
|
||||||
|
:style="{ left: `${offset}%` }"
|
||||||
|
@mousedown="handleMousedown"
|
||||||
|
>
|
||||||
|
<slot name="trigger">
|
||||||
|
<trigger-pane mode="vertical" />
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:style="{ left: `${offset}%` }"
|
||||||
|
class="right-pane"
|
||||||
|
:class="paneClasses"
|
||||||
|
>
|
||||||
|
<slot name="right" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else :class="`${prefix}-vertical`">
|
||||||
|
<div
|
||||||
|
:style="{ bottom: `${anotherOffset}%` }"
|
||||||
|
class="top-pane"
|
||||||
|
:class="paneClasses"
|
||||||
|
>
|
||||||
|
<slot name="top" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="`${prefix}-trigger-con`"
|
||||||
|
:style="{ top: `${offset}%` }"
|
||||||
|
@mousedown="handleMousedown"
|
||||||
|
>
|
||||||
|
<slot name="trigger">
|
||||||
|
<trigger-pane mode="horizontal" />
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:style="{ top: `${offset}%` }"
|
||||||
|
class="bottom-pane"
|
||||||
|
:class="paneClasses"
|
||||||
|
>
|
||||||
|
<slot name="bottom" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { oneOf, on, off } from './utils'
|
||||||
|
import TriggerPane from './triggerPane.vue'
|
||||||
|
export default {
|
||||||
|
name: 'SplitPane',
|
||||||
|
components: {
|
||||||
|
TriggerPane
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0.5
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
validator(value) {
|
||||||
|
return oneOf(value, ['horizontal', 'vertical'])
|
||||||
|
},
|
||||||
|
default: 'horizontal'
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: '40px'
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: '40px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Events
|
||||||
|
* @on-move-start
|
||||||
|
* @on-moving 返回值:事件对象,但是在事件对象中加入了两个参数:atMin(当前是否在最小值处), atMax(当前是否在最大值处)
|
||||||
|
* @on-move-end
|
||||||
|
*/
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
prefix: 'zj-split',
|
||||||
|
offset: 0,
|
||||||
|
oldOffset: 0,
|
||||||
|
isMoving: false,
|
||||||
|
computedMin: 0,
|
||||||
|
computedMax: 0,
|
||||||
|
currentValue: 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
wrapperClasses() {
|
||||||
|
return [`${this.prefix}-wrapper`, this.isMoving ? 'no-select' : '']
|
||||||
|
},
|
||||||
|
paneClasses() {
|
||||||
|
return [
|
||||||
|
`${this.prefix}-pane`,
|
||||||
|
{
|
||||||
|
[`${this.prefix}-pane-moving`]: this.isMoving
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
isHorizontal() {
|
||||||
|
return this.mode === 'horizontal'
|
||||||
|
},
|
||||||
|
anotherOffset() {
|
||||||
|
return 100 - this.offset
|
||||||
|
},
|
||||||
|
valueIsPx() {
|
||||||
|
return typeof this.value === 'string'
|
||||||
|
},
|
||||||
|
offsetSize() {
|
||||||
|
return this.isHorizontal ? 'offsetWidth' : 'offsetHeight'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
px2percent(numerator, denominator) {
|
||||||
|
return parseFloat(numerator) / parseFloat(denominator)
|
||||||
|
},
|
||||||
|
getComputedThresholdValue(type) {
|
||||||
|
let size = this.$refs.outerWrapper[this.offsetSize]
|
||||||
|
if (this.valueIsPx)
|
||||||
|
return typeof this[type] === 'string' ? this[type] : size * this[type]
|
||||||
|
else
|
||||||
|
return typeof this[type] === 'string'
|
||||||
|
? this.px2percent(this[type], size)
|
||||||
|
: this[type]
|
||||||
|
},
|
||||||
|
getMin(value1, value2) {
|
||||||
|
if (this.valueIsPx)
|
||||||
|
return `${Math.min(parseFloat(value1), parseFloat(value2))}px`
|
||||||
|
else return Math.min(value1, value2)
|
||||||
|
},
|
||||||
|
getMax(value1, value2) {
|
||||||
|
if (this.valueIsPx)
|
||||||
|
return `${Math.max(parseFloat(value1), parseFloat(value2))}px`
|
||||||
|
else return Math.max(value1, value2)
|
||||||
|
},
|
||||||
|
getAnotherOffset(value) {
|
||||||
|
let res = 0
|
||||||
|
if (this.valueIsPx)
|
||||||
|
res = `${
|
||||||
|
this.$refs.outerWrapper[this.offsetSize] - parseFloat(value)
|
||||||
|
}px`
|
||||||
|
else res = 1 - value
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
handleMove(e) {
|
||||||
|
let pageOffset = this.isHorizontal ? e.pageX : e.pageY
|
||||||
|
let offset = pageOffset - this.initOffset
|
||||||
|
let outerWidth = this.$refs.outerWrapper[this.offsetSize]
|
||||||
|
let value = this.valueIsPx
|
||||||
|
? `${parseFloat(this.oldOffset) + offset}px`
|
||||||
|
: this.px2percent(outerWidth * this.oldOffset + offset, outerWidth)
|
||||||
|
let anotherValue = this.getAnotherOffset(value)
|
||||||
|
if (parseFloat(value) <= parseFloat(this.computedMin))
|
||||||
|
value = this.getMax(value, this.computedMin)
|
||||||
|
if (parseFloat(anotherValue) <= parseFloat(this.computedMax))
|
||||||
|
value = this.getAnotherOffset(
|
||||||
|
this.getMax(anotherValue, this.computedMax)
|
||||||
|
)
|
||||||
|
e.atMin = this.value === this.computedMin
|
||||||
|
e.atMax = this.valueIsPx
|
||||||
|
? this.getAnotherOffset(this.value) === this.computedMax
|
||||||
|
: this.getAnotherOffset(this.value).toFixed(5) ===
|
||||||
|
this.computedMax.toFixed(5)
|
||||||
|
this.$emit('input', value)
|
||||||
|
this.$emit('on-moving', e)
|
||||||
|
},
|
||||||
|
handleUp() {
|
||||||
|
this.isMoving = false
|
||||||
|
off(document, 'mousemove', this.handleMove)
|
||||||
|
off(document, 'mouseup', this.handleUp)
|
||||||
|
this.$emit('on-move-end')
|
||||||
|
},
|
||||||
|
handleMousedown(e) {
|
||||||
|
this.initOffset = this.isHorizontal ? e.pageX : e.pageY
|
||||||
|
this.oldOffset = this.value
|
||||||
|
this.isMoving = true
|
||||||
|
on(document, 'mousemove', this.handleMove)
|
||||||
|
on(document, 'mouseup', this.handleUp)
|
||||||
|
this.$emit('on-move-start')
|
||||||
|
},
|
||||||
|
computeOffset() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.computedMin = this.getComputedThresholdValue('min')
|
||||||
|
this.computedMax = this.getComputedThresholdValue('max')
|
||||||
|
this.offset =
|
||||||
|
((this.valueIsPx
|
||||||
|
? this.px2percent(
|
||||||
|
this.value,
|
||||||
|
this.$refs.outerWrapper[this.offsetSize]
|
||||||
|
)
|
||||||
|
: this.value) *
|
||||||
|
10000) /
|
||||||
|
100
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
if (val !== this.currentValue) {
|
||||||
|
this.currentValue = val
|
||||||
|
this.computeOffset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.computeOffset()
|
||||||
|
})
|
||||||
|
|
||||||
|
on(window, 'resize', this.computeOffset)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
off(window, 'resize', this.computeOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.zj-split-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.zj-split-pane {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.zj-split-pane.left-pane,
|
||||||
|
.zj-split-pane.right-pane {
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane.left-pane {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane.right-pane {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane.top-pane,
|
||||||
|
.zj-split-pane.bottom-pane {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane.top-pane {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane.bottom-pane {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.zj-split-pane-moving {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* 开始 */
|
||||||
|
/* .zj-split-trigger {
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
} */
|
||||||
|
.zj-split-trigger-con {
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.zj-split-trigger-bar-con {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.zj-split-trigger-bar-con.vertical {
|
||||||
|
top: 50%;
|
||||||
|
height: 32px;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
|
.zj-split-trigger-bar-con.horizontal {
|
||||||
|
left: 50%;
|
||||||
|
height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
width: 32px;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
}
|
||||||
|
.zj-split-trigger-vertical {
|
||||||
|
width: 16px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #f2f4f9;
|
||||||
|
border-top: none;
|
||||||
|
border-bottom: none;
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
.zj-split-trigger-vertical .zj-split-trigger-bar {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
.zj-split-trigger-horizontal {
|
||||||
|
height: 16px;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #f2f4f9;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
cursor: row-resize;
|
||||||
|
}
|
||||||
|
.zj-split-trigger-horizontal .zj-split-trigger-bar {
|
||||||
|
width: 16px;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
position: relative;
|
||||||
|
bottom: 8px;
|
||||||
|
}
|
||||||
|
.zj-split-horizontal > .zj-split-trigger-con {
|
||||||
|
top: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
.zj-split-vertical > .zj-split-trigger-con {
|
||||||
|
left: 50%;
|
||||||
|
height: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.zj-split .no-select {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
45
src/components/SplitPane/triggerPane.vue
Normal file
45
src/components/SplitPane/triggerPane.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="classes">
|
||||||
|
<div :class="barConClasses">
|
||||||
|
<img
|
||||||
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAABACAYAAAB7jnWuAAAAAXNSR0IArs4c6QAAAjNJREFUaEPtWEFLG1EQfs9Eo4kUjJYieMklFKL0IlZX3JAiTcgmOaSJB09e+yd67rmnHorHHowJqMmaihddWS3kGigEqojQENqUEtKs2fBe2dSXowyPhWXh5TYw8+183+w3WQYjh3/Y4ecjcANF9WqBEHPNatiDUSerbFRZ86ra8HVJM8PiucDCUSwWMiDkwA0UyloeIbJngWKEGrlUNMwecHB69axv3DdZ7MdT84qyMoofa8Q9DZQqWoJQ8sFiQzG6ySvR14xZ6fTrLDGMSxb7AgEpHVv+aesIIGA8OeAR8IBDakQDYAWKZW2TIPr+v6z0Np+KZpnE1aoe7AwGJyz2TPri2c2Xv2wdgdgDh1/OQqaJXg1lHcN/3iTlfSaxrutTP9rmNovng+OfJUnq2ToCCBhPDvgl5AGH1LinAesfb2CYSxYrgsjffCqqM4b1en3i23VbZvHzUPA8Eon0bVVA2LB4fJEhhHx6+CD5nlPkVSaxqp4/7VJUH21Cr2cxG19v2ToCCBhPjntcwMMOUuMeBYqVM5lS/O6B1V0uJe8whuWyNmMgWmDxtNe7lUhIbVsVEHugVNHCFKP08HsIod+55MYuk/ioVvP3W723oxF4nnyMx190bR0BBIwnxz0u4GEHqREKgBUQ9wHHN6G4D0A8zZMDdgEPOKTGPQ2I+4Dje0DcByCW4slxjw3FfcBxG4r7AI/FIDXusSGEDU8OWAFxH3B8D4j7AM8bDqkBuwACxpPzDwGD3FDyRWhbAAAAAElFTkSuQmCC"
|
||||||
|
alt=""
|
||||||
|
:class="`${prefix}-bar`"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'triggerPane',
|
||||||
|
props: {
|
||||||
|
mode: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
prefix: 'zj-split-trigger',
|
||||||
|
initOffset: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isVertical() {
|
||||||
|
return this.mode === 'vertical'
|
||||||
|
},
|
||||||
|
classes() {
|
||||||
|
return [
|
||||||
|
this.prefix,
|
||||||
|
this.isVertical
|
||||||
|
? `${this.prefix}-vertical`
|
||||||
|
: `${this.prefix}-horizontal`
|
||||||
|
]
|
||||||
|
},
|
||||||
|
barConClasses() {
|
||||||
|
return [
|
||||||
|
`${this.prefix}-bar-con`,
|
||||||
|
this.isVertical ? 'vertical' : 'horizontal'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
45
src/components/SplitPane/utils.js
Normal file
45
src/components/SplitPane/utils.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
const isServer = Vue.prototype.$isServer
|
||||||
|
// 判断参数是否是其中之一
|
||||||
|
export function oneOf(value, validList) {
|
||||||
|
for (let i = 0; i < validList.length; i++) {
|
||||||
|
if (value === validList[i]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
export const on = (function () {
|
||||||
|
if (!isServer && document.addEventListener) {
|
||||||
|
return function (element, event, handler, useCapture = false) {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.addEventListener(event, handler, useCapture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.attachEvent('on' + event, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
export const off = (function () {
|
||||||
|
if (!isServer && document.removeEventListener) {
|
||||||
|
return function (element, event, handler, useCapture = false) {
|
||||||
|
if (element && event) {
|
||||||
|
element.removeEventListener(event, handler, useCapture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event) {
|
||||||
|
element.detachEvent('on' + event, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
Loading…
Reference in New Issue
Block a user