vue寫的一個拖拽容器

陳其文發表於2021-12-02
<template>
    <div class="container" :style="containerStyle" @mousedown="mousedown($event)">
        <div class="box-module" v-show="isDown">
            <div class="box-line box-left" :style="leftStyle" :data-value="leftWidth"></div>
            <div class="box-line box-right" :style="rightStyle" :data-value="rightWidth"></div>
            <div class="box-line box-top" :style="topStyle" :data-value="topWidth"></div>
            <div class="box-line box-bottom" :style="bottomStyle" :data-value="bottomWidth"></div>
        </div>
        <div class="box-slot">
            <slot></slot>
        </div>
    </div>
</template>

<script>
export default {
    name: "Container",
    props: {
        left: {
            type: Number,
            default: 300
        },
        top: {
            type: Number,
            default: 50
        },
    },
    data () {
        return {
            isDown: false,
            pos: {
                sx: 0,
                sy: 0,
                left: 0,
                top: 0,
                width: 0,
                height: 0,
            },
            box: {
                width: 0,
                height: 0
            }
        }
    },
    computed: {
        containerStyle () {
            return {
                left: this.pos.left + 'px',
                top: this.pos.top + 'px',
            }
        },
        leftWidth () {
            return this.pos.left + 'px'
        },
        rightWidth () {
            return (this.box.width - this.pos.left - this.pos.width) + 'px'
        },
        topWidth () {
            return this.pos.top + 'px'
        },
        bottomWidth () {
            return (this.box.height - this.pos.top - this.pos.height) + 'px'
        },
        leftStyle () {
            return {
                left: (-this.pos.left) + 'px',
                top: (this.pos.height / 2) + 'px',
                width: this.leftWidth,
            }
        },
        rightStyle () {
            return {
                left: this.pos.width + 'px',
                top: (this.pos.height / 2) + 'px',
                width: this.rightWidth,
            }
        },
        topStyle () {
            return {
                top: (-this.pos.top) + 'px',
                left: (this.pos.width / 2) + 'px',
                height: this.topWidth,
            }
        },
        bottomStyle () {
            return {
                top: this.pos.height + 'px',
                left: (this.pos.width / 2) + 'px',
                height: this.bottomWidth,
            }
        },
    },
    created () {
        this.pos.left = this.left
        this.pos.top = this.top
        this.box.width = 3840
        this.box.height = 1080
    },
    mounted () {
        this.children = this.$children[0]
        const rect = this.children.$el.getBoundingClientRect()
        this.pos.width = rect.width
        this.pos.height = rect.height
    },
    methods: {
        mouseup () {
            this.isDown = false
            document.removeEventListener('mouseup', this.mouseup)
            document.removeEventListener('mousemove', this.mousemove)
        },
        mousedown (event) {
            this.isDown = true
            this.rect = this.children.$el.getBoundingClientRect()
            this.pos.sx = event.pageX
            this.pos.sy = event.pageY
            document.addEventListener('mouseup', this.mouseup, false)
            document.addEventListener('mousemove', this.mousemove, false)
        },
        mousemove (event) {
            if (this.isDown) {
                const dx = event.pageX - this.pos.sx
                const dy = event.pageY - this.pos.sy
                this.pos.left = this.rect.left + dx
                this.pos.top = this.rect.top + dy
            }
        },
    },
    beforeDestroy () {
    }
}
</script>

<style scoped lang="scss">
.container{
    position: absolute;
    &:hover {
        z-index: 999;
    }
    .box-slot {
        position: relative;
        z-index: 1;
    }
    .box-module {
        position: relative;
        z-index: 0;
    }
    .box-line {
        position: absolute;
        background: red;
        &.box-left {
            height: 1px;
        }
        &.box-right {
            height: 1px;
        }
        &.box-top {
            width: 1px;
        }
        &.box-bottom {
            width: 1px;
        }
        &::after {
            position: absolute;
            color: red;
            font-size: 16px;
            content: attr(data-value);
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
    }
}
</style>

相關文章