vue3-draggable-resizable
Version:
[Vue3 Component] 拖拽缩放并具有自动吸附对齐、参考线等功能
127 lines (125 loc) • 3.14 kB
text/typescript
import { computed, defineComponent, h, provide, reactive, toRef } from 'vue'
import {
PositionStore,
Position,
UpdatePosition,
GetPositionStore,
MatchedLine,
SetMatchedLine
} from './types'
import { IDENTITY } from './utils'
export default defineComponent({
name: 'DraggableContainer',
props: {
disabled: {
type: Boolean,
default: false
},
adsorbParent: {
type: Boolean,
default: true
},
adsorbCols: {
type: Array,
default: null
},
adsorbRows: {
type: Array,
default: null
},
referenceLineVisible: {
type: Boolean,
default: true
},
referenceLineColor: {
type: String,
default: '#f00'
}
},
setup(props) {
const positionStore = reactive<PositionStore>({})
const updatePosition: UpdatePosition = (id: string, position: Position) => {
positionStore[id] = position
}
const getPositionStore: GetPositionStore = (excludeId?: string) => {
const _positionStore = Object.assign({}, positionStore)
if (excludeId) {
delete _positionStore[excludeId]
}
return _positionStore
}
const state = reactive<{
matchedLine: MatchedLine | null
}>({
matchedLine: null
})
const matchedRows = computed(
() => (state.matchedLine && state.matchedLine.row) || []
)
const matchedCols = computed(
() => (state.matchedLine && state.matchedLine.col) || []
)
const setMatchedLine: SetMatchedLine = (
matchedLine: MatchedLine | null
) => {
state.matchedLine = matchedLine
}
provide('identity', IDENTITY)
provide('updatePosition', updatePosition)
provide('getPositionStore', getPositionStore)
provide('setMatchedLine', setMatchedLine)
provide('disabled', toRef(props, 'disabled'))
provide('adsorbParent', toRef(props, 'adsorbParent'))
provide('adsorbCols', props.adsorbCols || [])
provide('adsorbRows', props.adsorbRows || [])
return {
matchedRows,
matchedCols
}
},
methods: {
renderReferenceLine() {
if (!this.referenceLineVisible) {
return []
}
return [
...this.matchedCols.map((item) => {
return h('div', {
style: {
width: '0',
height: '100%',
top: '0',
left: item + 'px',
borderLeft: `1px dashed ${this.referenceLineColor}`,
position: 'absolute'
}
})
}),
...this.matchedRows.map((item) => {
return h('div', {
style: {
width: '100%',
height: '0',
left: '0',
top: item + 'px',
borderTop: `1px dashed ${this.referenceLineColor}`,
position: 'absolute'
}
})
})
]
}
},
render() {
return h(
'div',
{
style: { width: '100%', height: '100%', position: 'relative' }
},
[
this.$slots.default && this.$slots.default(),
...this.renderReferenceLine()
]
)
}
})