vue设置元素拖拽,拉拽边缘缩放,设置选中元素始终在最顶层

实现功能:

设置多个元素中,元素的拖拽,拉拽边缘实现元素缩放,设置选中元素始终在最顶层

代码:

<template>
    <div id="pageBox" @mousewheel="mouseWheel" :style="{ width: imgWidth, height: imgHeight }">
        设备宽度
        <div v-for="(item,index) in list" :key="index" class="container" :style="select===index ? selectStyle : noselect(index)"  :id="'select'+index" @click="clickBox(item, index)">
            点击{{index}}
            <div class="point top" v-if="select===index"></div>
            <div class="point left" v-if="select===index"></div>
            <div class="point right" v-if="select===index"></div>
            <div class="point bottom" v-if="select===index"></div>
            <div class="point top-left" v-if="select===index"></div>
            <div class="point top-right" v-if="select===index"></div>
            <div class="point bottom-left" v-if="select===index"></div>
            <div class="point bottom-right" v-if="select===index"></div>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            list: [1, 2, 3, 4, 5],
            // 页面对象
            pageObj: null,
            // 缩放元素
            zoomBox: null,
            // 鼠标按下时的坐标,并在修改尺寸时保存上一个鼠标的位置
            clientX: 0,
            clientY: 0,
            // div可修改的最小宽高
            minW: 20,
            minH: 20,
            // 鼠标按下时的位置,使用n、s、w、e表示
            direc: '',
            select: '',
            selectStyle: {
                border: '1px dashed #19be6b',
                // zIndex: 100,
                cursor: 'pointer'
            },
            // 拖拽
            moveType: '',
            disX: 0,
            disY: 0,
            imgWidth: "500px",
            imgHeight: "500px"
        }
    },
    computed: {
        // 未选择的元素保持原有的z-indx层级
        noselect: function() {
            return function(index) {
                this.$nextTick(() => {
                    // dom元素更新后执行,因此这里能正确打印更改之后的值
                    let obj = document.getElementById('select' + index)
                    let sty = {
                        zIndex: obj.style.zIndex
                    }
                    return sty
                })
                return ''
            }
        }
    },
    created() {},
    mounted() {
        this.pageObj = document.getElementById('pageBox')
    },
    methods: {
        // 鼠标滚轮
        mouseWheel(e) {
            const img = document.getElementById("pageBox")
            this.imgWidth = img.offsetWidth || img.width || img.clientWidth
            this.imgHeight = img.offsetHeight || img.height || img.clientHeight
            if (e.deltaY > 0) {
                console.log("鼠标向下滚动,图片缩小")
                this.imgWidth = `${this.imgWidth - 10}px`
                this.imgHeight = `${this.imgHeight - 10}px`
            } else {
                console.log("鼠标向上滚动,图片放大")
                this.imgWidth = `${this.imgWidth + 10}px`
                this.imgHeight = `${this.imgHeight + 10}px`
            }
        },
        // 点击元素
        clickBox(item, index) {
            // 需要调整尺寸的div
            this.zoomBox = document.getElementById('select' + index)
            this.select = index
            // 设置元素的层级,当前点击的层级在最大层级上+1
            let zindex = this.setIndex()
            this.zoomBox.style.zIndex = zindex + 1
            // 鼠标按下事件
            this.zoomBox.onmousedown = this.zoomDown
            // 页面监听移动事件
            this.pageObj.onmousemove = this.mouseMove
            // 鼠标松开事件
            this.pageObj.onmouseup = this.zoomUp
        },
        // 设置元素浮层
        setIndex() {
            // 获取最大层级的元素z-index
            let max = 0
            for (let i = 0; i < this.list.length; i++) {
                let obj = document.getElementById('select' + i)
                if (obj.style.zIndex) {
                    if (max < obj.style.zIndex) {
                        max = parseInt(obj.style.zIndex)
                    }
                }
            }
            return max
        },
        // 鼠标按下
        zoomDown(e) {
            // 去除鼠标默认事件          
            document.oncontextmenu = function(e) {
                e.preventDefault()
            }
            // 阻止冒泡
            e.stopPropagation()
            let oEvent = e || event
            let d = this.getDirection(oEvent)
            this.zoomBox.onmouseup = this.boxUp
            // 当位置为四个边和四个角时才开启尺寸修改
            if (d === 'move' || d === '') {
                this.disX = oEvent.clientX - this.zoomBox.offsetLeft
                this.disY = oEvent.clientY - this.zoomBox.offsetTop
                this.moveType = 'drag'
                console.log('拖拽按下', this.disX, oEvent.clientX, this.zoomBox.offsetLeft)
            } else {
                this.moveType = 'resizeable'
                this.direc = d
                this.clientX = e.clientX
                this.clientY = e.clientY
                console.log('缩放按下')
            }
        },
        // 鼠标移动
        mouseMove(e) {
            let oEvent = e || event
            let d = this.getDirection(oEvent)
            let cursor = ''
            if (d === 'move' || d === '') {
                // 默认移动鼠标样式
                cursor = 'move' 
            } else {
                // 缩放鼠标样式
                cursor = d + '-resize'
            }
            // 修改鼠标显示效果
            this.zoomBox.style.cursor = cursor
            if (this.moveType === 'resizeable') {
                // 缩放
                this.zoomBox.style.cursor = this.direc + '-resize'
                this.zoomMove(oEvent)
            } else if (this.moveType === 'drag') {
                this.zoomBox.style.cursor = 'move'
                this.eleMousemove(oEvent)
            }
        },
        // 缩放移动
        zoomMove(e) {
            // 当开启尺寸修改时,鼠标移动会修改div尺寸
            if (this.moveType === 'resizeable') {
                // 鼠标按下的位置在右边,修改宽度
                if (this.direc.indexOf('e') !== -1) {
                    this.zoomBox.style.width = Math.max(this.minW, this.zoomBox.offsetWidth + (e.clientX - this.clientX)) + 'px'
                    this.clientX = e.clientX
                }
                // 鼠标按下的位置在上部,修改高度
                if (this.direc.indexOf('n') !== -1) {
                    this.zoomBox.style.height = Math.max(this.minH, this.zoomBox.offsetHeight + (this.clientY - e.clientY)) + 'px'
                    this.clientY = e.clientY
                }
                // 鼠标按下的位置在底部,修改高度
                if (this.direc.indexOf('s') !== -1) {
                    this.zoomBox.style.height = Math.max(this.minH, this.zoomBox.offsetHeight + (e.clientY - this.clientY)) + 'px'
                    this.clientY = e.clientY
                }
                // 鼠标按下的位置在左边,修改宽度
                if (this.direc.indexOf('w') !== -1) {
                    this.zoomBox.style.width = Math.max(this.minW, this.zoomBox.offsetWidth + (this.clientX - e.clientX)) + 'px'
                    this.clientX = e.clientX
                }
            }
        },
        // 鼠标拖拽移动
        eleMousemove(oEvent) {
            // 加入该判断拖拽更流畅
            if (this.moveType === 'drag') {
                // 计算点击元素到父级元素的定位top,left距离
                let l = oEvent.clientX - this.disX
                let t = oEvent.clientY - this.disY
                /** 限定拖拽范围,限定拖拽元素在指定的范围内 */
                // 限定左边界和上边界
                if (l < 0) {
                    l = 0
                }
                if (t < 0) {
                    t = 0
                }
                // 限定右边界的距离(当l=父元素宽-子元素宽时,刚好子元素放在父元素最右边)
                if (l > this.pageObj.clientWidth - this.zoomBox.clientWidth) {
                    l = this.pageObj.clientWidth - this.zoomBox.clientWidth
                }
                // 限定下边界的距离(当t=父元素高-子元素高时,刚好子元素放在父元素最下边)
                if (t > this.pageObj.clientHeight - this.zoomBox.clientHeight) {
                    t = this.pageObj.clientHeight - this.zoomBox.clientHeight
                }
                this.zoomBox.style.left = l + 'px'
                this.zoomBox.style.top = t + 'px'
            }
        },
        // 操作元素的鼠标抬起事件
        boxUp(e) {
            // 阻止冒泡
            e.stopPropagation()
            let oEvent = e || event
            console.log('box鼠标抬起')
            // 当前选择对象鼠标抬起事件
            this.moveType = ''
            this.zoomBox.onmousedown = null
            this.pageObj.onmousemove = null
            this.pageObj.onmouseup = null
        },
        // 操作元素的父级元素鼠标抬起事件
        zoomUp(e) {
            // 阻止冒泡
            e.stopPropagation()
            let oEvent = e || event
            console.log('父级鼠标抬起')
            // 点击当前选择的任意位置鼠标抬起事件,选择状态清空
            this.select = ''
            this.moveType = ''
            this.zoomBox.onmousedown = null
            this.zoomBox.onmouseup = null
            this.pageObj.onmousemove = null
            this.pageObj.onmouseup = null
        },
        // 获取鼠标所在div的位置
        getDirection(ev) {
            let dir = ''
            if (ev.target.className.indexOf('top') >= 0) {
                dir += 'n'
            } else if (ev.target.className.indexOf('bottom') >= 0) {
                dir += 's'
            }
            if (ev.target.className.indexOf('left') >= 0) {
                dir += 'w'
            } else if (ev.target.className.indexOf('right') >= 0) {
                dir += 'e'
            }
            if (ev.target.className === '') {
                dir = 'move'
            }
            return dir
        }
    }
}
</script>

<style lang="less" scoped>
#pageBox{
    border:1px solid red;
    width:800px;
    height:600px;
    position: relative;
    color:#fff;
}
.container {
    width: 150px;
    height: 150px;
    box-sizing: border-box;
    position: absolute;
    cursor: default;
    background: #757575;
}
.point{
    width: 10px;
    height: 10px;
    border-radius: 2px;
    border: 1px solid #19be6b;
    position: absolute;
}
.top{
    top: -5px;
    left: 50%;
}
.bottom{
    bottom: -5px;
    left: 50%;
}
.left{
    left: -5px;
    top: 50%;
}
.right{
    right: -5px;
    top: 50%;
}
.top-left{
    top: -5px;
    left: -5px;
}
.bottom-left{
    bottom: -5px;
    left: -5px;
}
.top-right{
    top: -5px;
    right: -5px;
}
.bottom-right{
    bottom: -5px;
    right: -5px;
}
</style>

解决上文中的拖拽缩放时左边缩放宽高不正确的问题,仅供参考

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        * {
            margin: 0;
            padding: 0
        }
        .box {
            width: 300px;
            height: 300px;
            position: absolute;
            top: 100px;
            left: 100px;
        }
        /*四边*/
        .box .t,
        .box .b,
        .box .l,
        .box .r {
            position: absolute;
            z-index: 1;
            background: #666;
        }
        .box .l,
        .box .r {
            width: 5px;
            height: 100%;
            cursor: col-resize;
        }
        .box .t,
        .box .b {
            width: 100%;
            height: 5px;
            cursor: row-resize;
        }
        .box .t {
            top: 0;
        }
        .box .b {
            bottom: 0;
        }
        .box .l {
            left: 0;
        }
        .box .r {
            right: 0;
        }
        /*四角*/
        .box .tl,
        .box .bl,
        .box .br,
        .box .tr {
            width: 20px;
            height: 20px;
            position: absolute;
            background: #fff;
            border:1px solid #666;
            z-index: 2;
            cursor: nwse-resize
        }
        .box .tl,
        .box .bl {
            left: -5px;
        }
        .box .tr,
        .box .br {
            right: -5px;
        }
        .box .br,
        .box .bl {
            bottom: -5px;
        }
        .box .tl,
        .box .tr {
            top: -5px;
        }
        .box .tr,
        .box .bl {
            cursor: nesw-resize;
        }
        /*内核*/
        .inner {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <!-- 将边线的缩放也加了 -->
    <div class="box" id="odiv">
        <span class="r"></span>
        <span class="l"></span>
        <span class="t"></span>
        <span class="b"></span>
        <span class="br"></span>
        <span class="bl"></span>
        <span class="tr"></span>
        <span class="tl"></span>
        <div class="inner"></div>
    </div>
    <script>
        window.onload = function () {
            var oDiv = document.getElementsByTagName('div')[0];
            oDiv.style.width = '500px';
            var aSpan = oDiv.getElementsByTagName('span');
            for (var i = 0; i < aSpan.length; i++) {
                dragFn(aSpan[i]);
            }
            function dragFn(obj) {
                obj.onmousedown = function (ev) {
                    var oEv = ev || event;
                    oEv.stopPropagation();
					// 元素的宽高
                    var oldWidth = oDiv.offsetWidth;
                    var oldHeight = oDiv.offsetHeight;
					// 当前边框元素鼠标点击到浏览器的距离
                    var oldX = oEv.clientX;
                    var oldY = oEv.clientY;
					// 当前点击元素到最近父元素的偏移距离
                    var oldLeft = oDiv.offsetLeft;
                    var oldTop = oDiv.offsetTop;

                    document.onmousemove = function (ev) {
                        var oEv = ev || event;
						// 居上面的距离
                        let disY = (oldTop + (oEv.clientY - oldY)),
						    // 鼠标点击到浏览器距离
                            disX = (oldLeft + (oEv.clientX - oldLeft));
                        if(disX>oldLeft+oldWidth){
							// 距离父元素的距离不能小于:距离父元素距离+自身宽高
                            disX=oldLeft+oldWidth
                        }
                        if(disY>oldTop+oldHeight){
                            disY=oldTop+oldHeight
                        }
						// 左上角
                        if (obj.className == 'tl') {
							// 自身宽高=原来宽高加(或者减去)缩放的宽高
                            oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
                            oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
							// 定位=距离父级元素的偏移距离
                            oDiv.style.left = disX + 'px';
                            oDiv.style.top = disY + 'px';
                        }
						// 左下角
                        else if (obj.className == 'bl') {
                            oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
                            oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
                            oDiv.style.left = disX + 'px';
                            // oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
							console.log('左下角', oDiv.style.bottom, oldTop, oEv.clientY, oldY)
                        }
						// 右上角
                        else if (obj.className == 'tr') {
                            oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
                            oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
                            oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
                            oDiv.style.top = disY + 'px';
                        }
						// 右下角
                        else if (obj.className == 'br') {
                            oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
                            oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
                            oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
                            oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
                        }
                        else if (obj.className == 't') {
                            oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
                            oDiv.style.top = disY + 'px';
                        }
                        else if (obj.className == 'b') {
                            oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
                            oDiv.style.bottom = disY + 'px';
                        }
                        else if (obj.className == 'l') {
                            oDiv.style.height = oldHeight + 'px';
                            oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
                            oDiv.style.left = disX + 'px';
                        }
                        else if (obj.className == 'r') {
                            oDiv.style.height = oldHeight + 'px';
                            oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
                            oDiv.style.right = disX + 'px';
                        }
                    };

                    document.onmouseup = function () {
                        document.onmousemove = null;
                    };
                    return false;
                };
            }
            document.getElementById("odiv").onmousedown = function (ev) {
                var oevent = ev || event;
                oevent.preventDefault();

                var distanceX = oevent.clientX - oDiv.offsetLeft;
                var distanceY = oevent.clientY - oDiv.offsetTop;

                document.onmousemove = function (ev) {
                    var oevent = ev || event;
                    oDiv.style.left = oevent.clientX - distanceX + 'px';
                    oDiv.style.top = oevent.clientY - distanceY + 'px';
                };
                document.onmouseup = function () {
                    document.onmousemove = null;
                    document.onmouseup = null;
                };
            }
        };
    </script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值