使用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>
原文地址:https://www.cnblogs.com/cjnmy36723/p/3952072.html