原生js实现拖拽移动与缩放效果

本文介绍了如何使用原生JavaScript实现元素的拖拽和缩放功能。首先,通过简单的代码实现了元素的拖拽效果。接着,通过设置方位并绑定缩放方法,实现了元素的缩放功能。最终,元素不仅可以被拖动,还可以进行自由缩放。实现过程中,利用鼠标位置和元素初始位置的关系来调整元素的坐标和大小。

效果图如下-实现了简单的拖拽和缩放功能
在这里插入图片描述

第一步—简单的拖拽功能
 // 创建一个MoveClass构造函数
    function MoveClass(id, options = {}) {
        // 绑定ele属性
        this.ele = document.querySelector(id);

        this.move();
    }
// 给MoveClass原型上绑定move方法
    MoveClass.prototype.move = function () {
        // ele的鼠标按下事件调用mousedown
        this.ele.onmousedown = e => {
            // 获取事件对象
            var e = e || window.event;
            // 鼠标按下时,鼠标相对于元素的x坐标
            var x = e.offsetX;
            // 鼠标按下时,鼠标相对于元素的y坐标
            var y = e.offsetY;
            // 鼠标按下移动时调用mousemove
            document.onmousemove = e => {
                // 元素ele移动的距离l
                var l = e.clientX - x;
                // 元素ele移动的距离l
                var t = e.clientY - y;
                this.ele.style.left = l + "px";
                this.ele.style.top = t + "px";
            }
            // 当鼠标弹起时,清空onmousemove与onmouseup
            document.onmouseup = () => {
                document.onmousemove = null;
                document.onmouseup = null;
            }
        }
    }
    // new一个MoveClass对象
    var moveClass = new MoveClass("#box");

效果如下,简单的拖拽
在这里插入图片描述

第二步—简单的缩放功能

1.设置方位

// ele的左,左上,左下,右,右上,右下,上,下
    MoveClass.prototype.editoptions = {
        left_top: true,
        left: true,
        right: true,
        top: true,
        bottom: true,
        right_top: true,
        left_bottom: true,
        right_bottom: true,
    }

2.给原型绑定缩放的方法

// 给原型绑定缩放的方法
    MoveClass.prototype.editEle = function () {
        // console.log(this.ele.clientWidth,this.ele.clientHeight);
        // console.log(this.ele.offsetLeft,this.ele.offsetTop);
        var that = this;
        // 创建一个div
        var div = document.createElement("div");
        // 遍历this.editoptions
        for (let attr in this.editoptions) {
            if (this.editoptions[attr]) {
                // 循环创建左,左上,左下,右,右上,右下,上,下方位的小点
                var dian = document.createElement("div");
                dian.className = "dian " + attr;
                // 设置类型为对应的attr
                dian.dataset.type = attr;
                // 当按下对应方位的小点时
                dian.onmousedown = e => {
                    var e = e || window.event;
                    // 先获取鼠标距离屏幕的left与top值
                    var clientXY = {
                        x: e.clientX,
                        y: e.clientY
                    }
                    // 获取鼠标按下时ele的宽高
                    var eleWH = {
                        width: this.ele.clientWidth,
                        height: this.ele.clientHeight,
                    }
                    // 阻止事件冒泡(针对父元素的move)
                    e.stopPropagation();
                    // 通过e.target获取精准事件源对应的type值
                    var type = e.target.dataset.type;
                    // 鼠标按下对应方位小点移动时,调用mousemove
                    document.onmousemove = function (e) {
                        // 查找type中是否包含”right“
                        if (type.indexOf('right') > -1) {
                            // console.log("right");
                            // 如果拖拽后的宽度小于最小宽度,就return出去
                            if (that.options.minWidth > eleWH.width + e.clientX - clientXY.x) {
                                return;
                            }
                            // ele拖拽后的宽度为:初始width+拖拽后鼠标距离屏幕的距离 - 第一次按下时鼠标距离屏幕的距离
                            that.ele.style.width = (eleWH.width + e.clientX - clientXY.x) + "px";
                        }
                        // 与”right“相同原理
                        if (type.indexOf("bottom") > -1) {
                            // console.log("bottom");
                            if (that.options.minHeight > eleWH.height + e.clientY - clientXY.y) {
                                return;
                            }
                            that.ele.style.height = (eleWH.height + e.clientY - clientXY.y) + "px"
                        }

                        if (type.indexOf("top") > -1) {
                            // console.log("top");
                            if (that.options.minHeight > eleWH.height - e.clientY + clientXY.y) {
                                return;
                            }
                            // ele拖拽后的高度为:初始height-拖拽后鼠标距离屏幕的距离 + 第一次按下时鼠标距离屏幕的距离
                            that.ele.style.height = (eleWH.height - e.clientY + clientXY.y) + "px";
                            // 重新设置ele的top值为此时鼠标距离屏幕的y值
                            that.ele.style.top = e.clientY + "px";
                        }
                        // 与”top“相同原理
                        if (type.indexOf("left") > -1) {
                            // console.log("left");
                            if (that.options.minWidth > eleWH.width - e.clientX + clientXY.x) {
                                return;
                            }
                            that.ele.style.width = (eleWH.width - e.clientX + clientXY.x) + "px";
                            // 重新设置ele的left值为此时鼠标距离屏幕的x值
                            that.ele.style.left = e.clientX + "px";
                        }
                    }
                    document.onmouseup = function () {
                        document.onmousemove = null;
                        document.onmouseup = null;
                    }
                }
            }
            // 将类名为”dian“的div添加到div中
            div.appendChild(dian);
        }
        // 为div设置类名
        div.className = "kuang"
        // 将类名为”kuang“的div添加到ele中
        this.ele.appendChild(div);
    }

效果图如下
在这里插入图片描述
最终效果,盒子可以拖动,可以缩放。
盒子上的8个小点采用定位放上去的,事先写好了样式

<style>
        * {
            margin: 0;
            padding: 0;
        }

        #box {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            left: 100px;
            top: 100px;
        }

        .kuang {
            box-sizing: border-box;
            border: 1px solid #0f0;
            width: 100%;
            height: 100%;
            position: relative;
        }

        .kuang .dian {
            position: absolute;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: #0f0;
        }

        .left_top {
            left: -5px;
            top: -5px;
        }

        .right_top {
            right: -5px;
            top: -5px;
        }

        .left_bottom {
            left: -5px;
            bottom: -5px;
        }

        .right_bottom {
            right: -5px;
            bottom: -5px;
        }

        .top {
            top: -5px;
            left: 50%;
            transform: translateX(-50%);
        }

        .bottom {
            bottom: -5px;
            left: 50%;
            transform: translateX(-50%);
        }

        .left {
            left: -5px;
            top: 50%;
            transform: translateY(-50%);
        }

        .right {
            right: -5px;
            top: 50%;
            transform: translateY(-50%);
        }
    </style>
<body>
    <div id="box" class="border"></div>
</body>

所有的代码能直接粘贴使用。缩放的原理其实就是鼠标按下去时,获取当前的鼠标位置和盒子的宽高,鼠标按下并移动后获取此时的鼠标位置。
拖拽后的宽高=初始宽高+(拖拽后鼠标距离屏幕的位置 - 第一次按下时鼠标距离屏幕的位置)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值