• 使用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>
  • 相关阅读:
    「USACO 2020 US Open Platinum」Exercise
    Equilateral Triangles
    [USACO 2020 February Platinum]Help Yourself
    「ICPC World Finals 2019」美丽的桥梁
    「ICPC World Finals 2019 何以伊名始
    COCI20162017 Contest#6 F
    COCI2016/2017 Contest#3 F Meksikanac
    TopCoder SRM 570 Div1 CurvyonRails
    COCI2016-2017 Contest#2 F
    UOJ Round Good Bye JiHai D. 新年的追逐战
  • 原文地址:https://www.cnblogs.com/cjnmy36723/p/3952072.html
Copyright © 2020-2023  润新知