zoukankan      html  css  js  c++  java
  • 使用JS制作一个鼠标可拖的DIV(二)——限制区域移动

    这次是要对上一篇的内容进行扩展。

    由于需要对可拖动的 DIV 进行一个区域范围的限制,所以要给于一个容器,让可拖动的 DIV 元素不能逃出该容器的大小范围。

    一、思路

    1.在外层增加一个 DIV 容器,并设置好容器的大小。(即:宽和高)

    当容器存在边框的时候,由于这里还没找到获取的方法,所以,在容器边框大于 0 的时候,获得的容器的限制区域的坐标会有误差。

    为了避免这情况,可以在多加一次容器,有边框样式的在外层,无边框样子的在内层。

    例:

    <style>
        #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: 50px;
            height: 50px;
            top: 50px;
            left: 50px;
            z-index: 3;
        }
    </style>
    
    <div id="mainContainer">
        <div id="innerContainer">
            <div id="Drag" onmousedown="moveBind(this, event)">1</div>
            <div id="Drag2" onmousedown="moveBind(this, event)">2</div>
        </div>
    </div>
    <br />拖放状态:<span id="idShow">未开始</span>

    2.为了方便获得元素的位置和大小,先写一个方法来辅助(谷歌不能用了可恶orz,只能百度出这个方法并稍微做点修改)。

        //获得元素的坐标与大小。
        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];
            }
        }

    这里以数组的形式返回元素的 X 开始坐标和 Y 开始坐标,X 结束坐标和 Y 结束坐标,元素真实的宽与高(不算边框)

    3.在鼠标按下事件里,先获得容器的位置数据:

    //获得容器坐标。
    var container = findPosition(document.getElementById("innerContainer"));
    var containerLeft = container[0];
    var containerTop = container[1];
    var containerWidth = container[4];
    var containerHeight = container[5];

    4.计算拖动 DIV 元素可移动的区域坐标:

    /*计算出容器的范围坐标。*/
    
    //开始 X 坐标。
    var startX = containerLeft;
    //开始 Y 坐标。
    var startY = containerTop;
    //结束 X 坐标。
    var maxX = startX + containerWidth - width;
    //结束 Y 坐标。
    var maxY = startY + containerHeight - height;

    开始 X 坐标 = 容器的左上角 X 坐标。

    开始 Y 坐标 = 容器的左上角 Y 坐标。

    结束 X 坐标 = 开始 X 坐标 + 容器的宽度 - 拖动 DIV 元素的宽度

    结束 Y 坐标 = 开始 Y 坐标 + 容器的高度 - 拖动 DIV 元素的高度

    5.当区域内存在多个可拖动的 DIV 元素时,要把当前鼠标点击的那个 DIV 设置成置顶显示。

        //获得最大 Z 坐标。
        function getMaxIndex() {
            var index = 0;
            var ds = document.getElementById('innerContainer').getElementsByTagName('div');
            var length = document.getElementById('innerContainer').getElementsByTagName('div').length;
    
            for (var loop = 0; loop < length; loop++) {
                if (ds[loop].style.zIndex > index) index = ds[loop].style.zIndex;
            }
    
            return parseInt(index);
        }

    该方法遍历容器内的所有 DIV 元素(即:可拖动元素),取得它们当中z-Index最大的值。

    然后,设置点击元素的 z-Index 值:

    //鼠标选中的元素设置成顶层。
    obj.style.zIndex = getMaxIndex() + 1;

    /*******************以上方法是在鼠标按下事件里 onmousedown  ******************/

    /*******************以下方法是在鼠标按下事件里 onmousemove ******************/

    6.在移动事件里,修改元素位置的外层加上如下这条件。

                //不可以超出指定的范围。
                if (moveLeft >= startX && moveTop >= startY && moveLeft <= maxX && moveTop <= maxY) {
                    //当移动位置在范围内时,元素跟随鼠标移动。
                    obj.style.left = moveLeft + "px";
                    obj.style.top = moveTop + "px";
                }

    这条件表示:移动的位置在容器范围内时,元素才可以跟随鼠标移动。

    但是,现在这样的做法,当鼠标快速拖出容器区域时,元素就会停止不动,但并没有移动到最边界,同时,鼠标在区域外并没有放开按键,移动鼠标时元素并不会跟着移动。

    解决的思路是:

    (1)当元素水平(X坐标)移动的位置没有达到或超出容器限制区域的 X 坐标区域时。

    继续修改拖动元素的 X 坐标位置。

    (2)当元素水平(X坐标)移动的位置超出容器限制区域的最大 X 坐标(即:容器右下角的 X 坐标)区域时(即:限制区域的右边),将元素的 X 坐标设置成最大 X 坐标值。

    if (moveLeft >= startX && moveLeft <= maxX) {
                        obj.style.left = moveLeft + "px";
                    } else if (moveLeft > maxX) {
                        obj.style.left = maxX + "px";
                    }

    (3)当元素水平(X坐标)移动的位置小于容器限制区域的开始 X 坐标(即:容器左上角的 X 坐标)区域时(即:限制区域的左边),将元素的 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";
                    }

    (4)Y 坐标同以上(1)(2)(3):

                    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";
                    }

    完成了!这时,鼠标拖动到区域外面时,元素同样会跟随鼠标的位置在容器内移动。

    二、以下是完整源码:

    JS部分:

        //获得元素的坐标与大小。
        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];
            }
        }
    
        function moveBind(obj, evnt) {
            //获得元素坐标。
            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("innerContainer"));
            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 (doc) {
                //计算出移动后的坐标。
                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";
                    }
                }
    
                show("idShow", moveLeft, moveTop);
            }
    
            document.onmouseup = function () {
                document.onmousemove = function () { }
            };
        }
    
        //获得最大 Z 坐标。
        function getMaxIndex() {
            var index = 0;
            var ds = document.getElementById('innerContainer').getElementsByTagName('div');
            var length = document.getElementById('innerContainer').getElementsByTagName('div').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;
        }

    HTML部分:

    <style>
        #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: 50px;
            height: 50px;
            top: 50px;
            left: 50px;
            z-index: 3;
        }
    </style>
    
    <div id="mainContainer">
        <div id="innerContainer">
            <div id="Drag" onmousedown="moveBind(this, event)">1</div>
            <div id="Drag2" onmousedown="moveBind(this, event)">2</div>
        </div>
    </div>
    <br />拖放状态:<span id="idShow">未开始</span>
  • 相关阅读:
    在firefox里面查看AMF信息
    addFrameScript 修改自定义button 名字
    [转]游戏UI与flash 组件开发
    as 运算符 与 where T : class
    Process.Start传参
    站长工具
    SaveFileDialog使用方法
    iis admin service 无法设置 因为不是服务器?
    将文件夹层次显示在treeview控件中
    磁盘fat32转NTFS
  • 原文地址:https://www.cnblogs.com/cjnmy36723/p/3945152.html
Copyright © 2011-2022 走看看