zoukankan      html  css  js  c++  java
  • 使用JS制作一个鼠标可拖的DIV(四)——缩放

    原理与鼠标拖动 DIV 相同。

    下面就先实现一个在DIV的右上角显示一个小正方形(类似)。

    当鼠标按下并拖动时,DIV会以要拖动的元素的左下角的坐标点定位,根据鼠标的拖动,按比例的扩大或缩小。

    一、思路

    1、鼠标按时事件。

    这里要初始化数据。

    同移动一样,给小正方形绑定鼠标按时事件。

    (1)获得并保存要移动的元素(parent)的宽(parentWidth)与高(parentHeight)。

    即:元素缩放前的宽与高。

    (2)由于是要按比例缩放,所以,要在这时计算出宽与高的比例(scale),得到的结果保留一位小数。

    (3)获得鼠标的 X 坐标(mouseX),用于计算鼠标移动前与移动后的位置。

    2、鼠标拖动事件。

    同移动一样,给 document 帮绑定移动事件。

    由于小正方形是放在元素(parent)中的,为了避免绑定的鼠标按下事件与元素(parent)中相同的事件有冲突。

    所以,在绑定document.onmousemove前,要先清空元素(parent)的onmousedown事件。

    parent.onmousedown = function () { }
    document.onmousemove = function (doc) {
    }

    (1)计算出:鼠标移动的差值(moveWidth) = 移动后的鼠标坐标(currentMouseX) - 移动前的鼠标坐标(mouseX)。

    (2)元素(parent)缩放后的宽度(width) = 元素(parent)当前的宽度 + 鼠标移动的差值(moveWidth)

    (3)元素(parent)缩放后的高度(height) = 元素(parent)缩放的后的宽度(width)X (1 / 宽与高的比例(scale))

    即:height = width X (1 / scale)

    注意,这里要使用四舍五入来取整。

    (4)由于是要以元素(parent)左下角的坐标为定点,所以需要计算出元素(parent)左上角的 Y 坐标(top)的偏移量。

    元素(parent)左上角的 Y 坐标(top) = 元素(parent)当前左上角的 Y 坐标 - (元素(parent)缩放后的高度(height) - 元素(parent)缩放前的高度(parentHeight))

    即:

    top = parent.offsetTop - (height - parentHeight);

    设置元素(parent)左上角的 Y 坐标。

    设置元素(parent)缩放后的宽度。

    设置元素(parent)缩放后的高度。

    parent.style.top = top + "px";
    parent.style.width = width + "px";
    parent.style.height = height + "px";

    更新当前鼠标的 X 坐标(mouseX)。

    更新当前元素的宽度(parentWidth)。

    更新当前元素的高度(parentHeight)。

    mouseX = currentMouseX;
    parentWidth = parent.offsetWidth;
    parentHeight = parent.offsetHeight;

    3.鼠标放开事件

    当鼠标放开时:

    清除 document.onmousemove 事件。

    重新绑定(parent)的 onmousedown 事件到 moveBind 函数。

    二、实现

    续上篇

    首先,在元素(parent)里增加一个子DIV并绑定onmousedown事件到zoomBind函数,做为右上角的小正方形。

    在 addElement 函数里增加:

    var rightSize = "<div class='resize' onmousedown='zoomBind(this, event)'></div>";

    CSS样式是:

        .resize {
            width: 7px;
            height: 7px;
            background-color: #ddd;
            border: 1px solid #000;
            top: -5px;
            right: -5px;
            position: absolute;
            cursor: ne-resize;
        }

    为了避免事件冲突,在 moveBind 函数的最开始增加一个 bool 类型的变量,当鼠标按下时,设置为 true, 放开时,设置为 false。

    function moveBind(obj, evnt) {
            isMouseMove = true;
            /*...*/
    }

    moveBind 函数里绑定的onmouseup 事件:

    document.onmouseup = function () {
                isMouseMove = false;
                document.onmousemove = function () { }
            };

    现在创建zoomBind函数:

    //是否元素缩放。
    var isMouseZoom = false;
    
       function zoomBind(obj, evnt) {
            isMouseZoom = true;
    
            //设置最小宽度。
            var minWidth = 50;
    
            //获得元素对象。
            var parent = obj.parentNode;
    
            //获得当前鼠标位置。
            var mouseX = evnt.clientX;
    
            //获得元素的宽与高。
            var parentSize = findPosition(parent);
    
            var parentWidth = parentSize[4];
            var parentHeight = parentSize[5];
    
            //计算出宽与高的比例。
            var scale = (parentWidth / parentHeight).toFixed(1);
    
            parent.onmousedown = function () { }
            document.onmousemove = function (doc) {
                if (isMouseZoom) {
                    //设置成绝对定位,让元素可以移动。
                    parent.style.position = "absolute";
    
                    //获得鼠标移动后的坐标。
                    var currentMouseX = doc.clientX;
    
                    //计算出移动后的坐标。
                    var moveWidth = currentMouseX - mouseX;
    
                    //计算宽度增加或减少的值,增加的量等于鼠标移位的量。
                    var width = parent.offsetWidth + moveWidth;
    
                    if (width > minWidth) {
                        //高度参数是:当前宽度的值 * (1 / 宽与高的比例)
                        var height = Math.round(width * (1 / scale));
    
                        //以元素左下角为定点,则左下角的 Y 坐标 = 当前元素的左上角的 Y 坐标 - (改变后的高度 - 改变前的高度)
                        var top = parent.offsetTop - (height - parentHeight);
    
                        parent.style.top = top + "px";
                        parent.style.width = width + "px";
                        parent.style.height = height + "px";
    
                        mouseX = currentMouseX;
                        parentWidth = parent.offsetWidth;
                        parentHeight = parent.offsetHeight;
                    }
                }
            }
    
            document.onmouseup = function () {
                isMouseZoom = false;
                document.onmousemove = function () { }
                parent.onmousedown = function (e) {
                    moveBind(parent, e);
                }
            };
        }

    以下是完整源码:

    这里使用的是 jquery-1.10.2.min.js

    /*要引入 jquery */
    
        //禁止鼠标选中。
        document.onselectstart = new Function("event.returnValue=false;");
    
        var containerId = "innerContainer";
        var showId = "idShow";
        var moveElement = "div";
    
        //是否元素移动。
        var isMouseMove = false;
    
        //是否元素缩放。
        var isMouseZoom = false;
    
        var productLists = $("#products");
    
        //获得容器坐标。
        var setContainer = findPosition(document.getElementById(containerId));
    
        $("#ContainerWidth").attr("value", setContainer[4]);
        $("#ContainerHeight").attr("value", setContainer[5]);
    
        function addElement(obj) {
            var container = findPosition(document.getElementById(containerId));
            var containerLeft = container[0];
            var containerTop = container[1];
            var containerWidth = container[4];
            var containerHeight = container[5];
    
            //设置默认宽度与高度。
            var width = 50;
            var height = width * (1 / (obj.offsetWidth / obj.offsetHeight));
    
            var left = containerLeft + containerWidth / 2 - width / 2;
            var top = containerTop + containerHeight / 2 - height / 2;
    
            var style = "" + width + "px;height:" + height + "px; left:" + left + "px;top:" + top + "px; position:absolute;background: #ff0000;";
            var rightSize = "<div class='resize' onmousedown='zoomBind(this, event)'></div>";
            $("#" + containerId).append("<div onmousedown='moveBind(this, event)' onmousemove="this.style.cursor='move'" style='" + style + "'>" + rightSize + "</div>");
    
        }
    
        /****************************以下是元素缩放*******************************/
    
        function zoomBind(obj, evnt) {
            isMouseZoom = true;
    
            //设置最小宽度。
            var minWidth = 50;
    
            //获得元素对象。
            var parent = obj.parentNode;
    
            //获得当前鼠标位置。
            var mouseX = evnt.clientX;
    
            //获得元素的宽与高。
            var parentSize = findPosition(parent);
    
            var parentWidth = parentSize[4];
            var parentHeight = parentSize[5];
    
            //计算出宽与高的比例。
            var scale = (parentWidth / parentHeight).toFixed(1);
    
            parent.onmousedown = function () { }
            document.onmousemove = function (doc) {
                if (isMouseZoom) {
                    //设置成绝对定位,让元素可以移动。
                    parent.style.position = "absolute";
    
                    //获得鼠标移动后的坐标。
                    var currentMouseX = doc.clientX;
    
                    //计算出移动后的坐标。
                    var moveWidth = currentMouseX - mouseX;
    
                    //计算宽度增加或减少的值,增加的量等于鼠标移位的量。
                    var width = parent.offsetWidth + moveWidth;
    
                    if (width > minWidth) {
                        //高度参数是:当前宽度的值 * (1 / 宽与高的比例)
                        var height = Math.round(width * (1 / scale));
    
                        //以元素左下角为定点,则左下角的 Y 坐标 = 当前元素的左上角的 Y 坐标 - (改变后的高度 - 改变前的高度)
                        var top = parent.offsetTop - (height - parentHeight);
    
                        parent.style.top = top + "px";
                        parent.style.width = width + "px";
                        parent.style.height = height + "px";
    
                        mouseX = currentMouseX;
                        parentWidth = parent.offsetWidth;
                        parentHeight = parent.offsetHeight;
                    }
                }
            }
    
            document.onmouseup = function () {
                isMouseZoom = false;
                document.onmousemove = function () { }
                parent.onmousedown = function (e) {
                    moveBind(parent, e);
                }
            };
        }
    
        /****************************以上是元素缩放*******************************/
    
        /****************************以下是元素拖动*******************************/
        //绑定移动事件。
        function moveBind(obj, evnt) {
            isMouseMove = true;
    
            //获得元素坐标。
            var left = obj.offsetLeft;
            var top = obj.offsetTop;
            var width = obj.offsetWidth;
            var height = obj.offsetHeight;
    
            //计算出鼠标的位置与元素位置的差值。
            var cleft = evnt.clientX - left;
            var ctop = evnt.clientY - top;
    
            //获得容器坐标。
            var container = findPosition(document.getElementById(containerId));
            var containerLeft = container[0];
            var containerTop = container[1];
            var containerWidth = container[4];
            var containerHeight = container[5];
    
            /*计算出容器的范围坐标。*/
    
            //开始 X 坐标。
            var startX = containerLeft;
            //开始 Y 坐标。
            var startY = containerTop;
            //结束 X 坐标。
            var maxX = startX + containerWidth - width;
            //结束 Y 坐标。
            var maxY = startY + containerHeight - height;
    
            //鼠标选中的元素设置成顶层。
            obj.style.zIndex = getMaxIndex() + 1;
    
            //输出显示。
            //show("idShow", startX, startY);
            document.onmousemove = function () { }
            document.onmousemove = function (doc) {
    
                if (isMouseMove) {
                    //计算出移动后的坐标。
                    var moveLeft = doc.clientX - cleft;
                    var moveTop = doc.clientY - ctop;
    
                    //设置成绝对定位,让元素可以移动。
                    obj.style.position = "absolute";
    
                    //不可以超出指定的范围。
                    if (moveLeft >= startX && moveTop >= startY && moveLeft <= maxX && moveTop <= maxY) {
                        //当移动位置在范围内时,元素跟随鼠标移动。
                        obj.style.left = moveLeft + "px";
                        obj.style.top = moveTop + "px";
                    } else {
                        /****************以下为处理当鼠标的位置不在范围内里,鼠标的移动,里面的元素也要跟着移动*****************/
                        //向右移动时,如果移动坐标没有大于最大 X 坐标,则移动,否则设置成最大 X 坐标的值。
                        if (moveLeft >= startX && moveLeft <= maxX) {
                            obj.style.left = moveLeft + "px";
                        } else if (moveLeft > maxX) {
                            obj.style.left = maxX + "px";
                        } else if (moveLeft < startX) {
                            obj.style.left = startX + "px";
                        }
    
                        //向下移动时,如果移动坐标没有大于最大 Y 坐标,则移动,否则设置成最大 Y 坐标的值。
                        if (moveTop >= startY && moveTop <= maxY) {
                            obj.style.top = moveTop + "px";
                        } else if (moveTop > maxY) {
                            obj.style.top = maxY + "px";
                        } else if (moveTop < startY) {
                            obj.style.top = startY + "px";
                        }
                    }
    
                    var objX = obj.offsetLeft - startX;
                    var objY = obj.offsetTop - startY;
    
                    var inputValue = obj.getElementsByTagName("input")[0];
    
                    inputValue.value = objX + "," + objY + "," + width + "," + height;
    
                    show(showId, moveLeft, moveTop);
                }
            }
    
            document.onmouseup = function () {
                isMouseMove = false;
                document.onmousemove = function () { }
            };
        }
    
        //获得元素的坐标与大小。
        function findPosition(oElement) {
            var x2 = 0;
            var y2 = 0;
            var width = oElement.clientWidth;
            var height = oElement.clientHeight;
            //alert(width + "=" + height);
            if (typeof (oElement.offsetParent) != 'undefined') {
                for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) {
                    posX += oElement.offsetLeft;
                    posY += oElement.offsetTop;
                }
                x2 = posX + width;
                y2 = posY + height;
                return [posX, posY, x2, y2, width, height];
    
            } else {
                x2 = oElement.x + width;
                y2 = oElement.y + height;
                return [oElement.x, oElement.y, x2, y2, width, height];
            }
        }
    
        //获得最大 Z 坐标。
        function getMaxIndex() {
            var index = 0;
            var ds = document.getElementById(containerId).getElementsByTagName(moveElement);
            var length = document.getElementById(containerId).getElementsByTagName(moveElement).length;
    
            for (var loop = 0; loop < length; loop++) {
                if (ds[loop].style.zIndex > index) index = ds[loop].style.zIndex;
            }
    
            return parseInt(index);
        }
    
        //显示坐标信息。
        function show(id, x, y) {
            document.getElementById(id).innerHTML = "left:" + x + ";top:" + y;
        }
    
        /*****************************以上是元素拖动*******************************/

    完整CSS:

        .resize {
            width: 7px;
            height: 7px;
            background-color: #ddd;
            border: 1px solid #000;
            top: -5px;
            right: -5px;
            position: absolute;
            cursor: ne-resize;
        }
    
        #mainContainer {
            border: 10px solid #990000;
            width: 600px;
            height: 300px;
        }
    
        #innerContainer {
            width: 100%;
            height: 100%;
        }
    
        #Drag {
            /*border: 5px solid #C4E3FD;*/
            background: #C4E3FD;
            width: 50px;
            height: 50px;
            top: 50px;
            left: 50px;
            z-index: 2;
        }
    
        #Drag2 {
            /*border: 5px solid #C4E3FD;*/
            background: #ff0000;
            width: 80px;
            height: 80px;
            top: 50px;
            left: 50px;
            z-index: 3;
            /*background: url(http://pic.cnitblog.com/face/614265/20140725231849.png) no-repeat;*/
        }

    完整 HTML:

    <div id="mainContainer">
        <div id="innerContainer">
        </div>
    </div>
    
    <br />拖放状态:<span id="idShow">未开始</span>
    <br /><span id="testShow"></span>
    <div>
        <img src="http://pic.cnitblog.com/face/614265/20140725231849.png" onclick="addElement(this)" />
    </div>
  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/cjnmy36723/p/3952072.html
Copyright © 2011-2022 走看看