JavaScript DOM 鼠標拖拽|8月更文挑戰

鼠標行爲座標系

  1. 鼠標行爲觸發事件時,事件對象上會有一些屬性提供鼠標的位置信息javascript

    屬性 功能 兼容性
    clientX/Y 鼠標相對可視區域的座標 /
    x/y 與 clientX/Y 功能相同 firefox 低版本不支持
    pageX/Y 鼠標相對整個文檔的座標 兼容 IE9 及以上
    layerX/Y 與 pageX/Y 功能相同 IE10 及如下同 clientX/Y
    screenX/Y 鼠標位置相對屏幕座標 /
    offsetX/Y 鼠標位置相對塊元素的座標(包含邊框) safari 不包含邊框
  2. 獲取鼠標相對整個文檔的座標css

    pageX/Y 兼容性差,須要進行封裝html

    鼠標相對整個文檔的座標 = 鼠標相對可視區域的座標 + 滾動條滾動距離 - 文檔偏移java

    注:document.documentElement.clientTop 獲取文檔偏移,在 IE 一些版本中爲 undefined數組

    function pagePos(ev) {
        var sTop = getScrollOffset().top,
            sLeft = getScrollOffset().left,
            cTop = document.documentElement.clientTop || 0,
            cLeft = document.documentElement.clientLeft || 0;
        return {
            X: ev.clientX + sLeft - cLeft,
            Y: ev.clientY + sTop - cTop
        }
    }
    // 封裝的函數:獲取滾動條滾動距離
    function getScrollOffset() {
        if (window.pageXOffset) {
            return {
                top: window.pageYOffset,
                left: window.pageXOffset
            }
        }
        else return {
            top:document.body.scrollTop || document.documentElement.scrollTop,
            left:document.body.scrollLeft || document.documentElement.scrollLeft
        }
    }
    複製代碼

拖拽函數封裝

  1. 拖拽效果基於鼠標事件:mousedown、mousemove、mouseupmarkdown

    分別爲鼠標按下、鼠標移動、鼠標鬆開函數

  2. 原理工具

    鼠標按下時,添加鼠標移動、鼠標鬆開的事件處理函數ui

    鼠標移動時獲取鼠標座標,改變元素樣式this

    鼠標鬆開時清除鼠標移動和鼠標鬆開的事件處理函數

    <!doctype html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>Index</title>
        <style type="text/css"> .box { position: absolute; top: 0; left: 0; width: 100px; height: 100px; background-color: red; } </style>
    </head>
    <body>
    <div class="box"></div>
    <script> var box = document.getElementsByTagName('div')[0]; box.onmousedown = function (ev) { var ev = ev || window.event, x = pagePos(ev).X - parseInt(getStyles(box)['left']), y = pagePos(ev).Y - parseInt(getStyles(box)['top']); document.onmousemove = function (ev) { var ev = ev || window.event, mPos = pagePos(ev); box.style.left = mPos.X - x + 'px'; box.style.top = mPos.Y - y + 'px'; } document.onmouseup = function () { this.onmousemove = null; this.onmouseup = null; } } // 封裝的函數:獲取鼠標相對整個文檔的座標 function pagePos(ev) { var sTop = getScrollOffset().top, sLeft = getScrollOffset().left, cTop = document.documentElement.clientTop || 0, cLeft = document.documentElement.clientLeft || 0; return { X: ev.clientX + sLeft - cLeft, Y: ev.clientY + sTop - cTop } } // 封裝的函數:獲取滾動條滾動距離 function getScrollOffset() { if (window.pageXOffset) { return { top: window.pageYOffset, left: window.pageXOffset } } else return { top: document.body.scrollTop || document.documentElement.scrollTop, left: document.body.scrollLeft || document.documentElement.scrollLeft } } // 封裝的函數:獲取元素樣式的類數組 function getStyles(elem) { if (window.getComputedStyle) { return window.getComputedStyle(elem, null); } else return elem.currentStyle; } </script>
    </body>
    </html>
    複製代碼
  3. 封裝拖拽函數

    先封裝幾個工具函數,如綁定事件處理函數、獲取滾動條滾動距離、獲取元素樣式、阻止冒泡和默認事件等

    // 綁定事件處理函數
    function addEvent(elem, type, fn) {
        if (elem.addEventListener) {
            elem.addEventListener(type, fn);
        } else if (elem.attachEvent) {
            elem.attachEvent('on' + type, function (ev) {
                fn.call(elem, ev); // call 兼容性比 bind 好
            });
        } else {
            elem['on' + type] = fn;
        }
    }
    // 解綁事件處理函數
    function removeEvent(elem, type, fn) {
        if (elem.addEventListener) {
            elem.removeEventListener(type, fn);
        } else if (elem.attachEvent) {
            elem.detachEvent('on' + type, fn);
        } else {
            elem['on' + type] = null;
        }
    }
    // 獲取鼠標在整個文檔中的座標
    function pagePos(ev) {
        var sTop = getScrollOffset().top,
            sLeft = getScrollOffset().left,
            cTop = document.documentElement.clientTop || 0,
            cLeft = document.documentElement.clientLeft || 0;
        return {
            X: ev.clientX + sLeft - cLeft,
            Y: ev.clientY + sTop - cTop
        }
    }
    // 獲取滾動條滾動距離
    function getScrollOffset() {
        if (window.pageXOffset) {
            return {
                top: window.pageYOffset,
                left: window.pageXOffset
            }
        } else return {
            top: document.body.scrollTop || document.documentElement.scrollTop,
            left: document.body.scrollLeft || document.documentElement.scrollLeft
        }
    }
    // 獲取元素樣式的類數組
    function getStyles(elem) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(elem, null);
        } else return elem.currentStyle;
    }
    // 阻止冒泡
    function cancelBubble(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else ev.cancelBubble = true; // 兼容 IE8 及如下
    }
    // 阻止默認事件
    function preventDefaultEvent(ev) {
        if (ev.preventDefault) {
            ev.preventDefault();
        } else ev.returnValue = false; // 兼容 IE8 及如下
    }  
    複製代碼

    按下鼠標mousedown事件觸發,經過事件對象獲取鼠標位置,注意減去元素的尺寸

    移動鼠標mousemove事件觸發,改變目標元素的行內樣式,達到移動位置的效果

    鬆開鼠標mouseup事件觸發,解綁mousedownmousemove事件

    var box = document.getElementsByTagName('div')[0];
    elemDrag(box);
    
    // 封裝的拖拽函數
    function elemDrag(elem) {
        var x,
            y;
        addEvent(elem, 'mousedown', function (ev) {
            var ev = ev || window.event;
            x = pagePos(ev).X - parseInt(getStyles(elem)['left']);
            y = pagePos(ev).Y - parseInt(getStyles(elem)['top']);
            addEvent(document, 'mousemove', mousemove);
            addEvent(document, 'mouseup', mouseup);
            cancelBubble(ev);
            preventDefaultEvent(ev);
        });
    
        function mousemove(ev) {
            var ev = ev || window.event;
            elem.style.left = pagePos(ev).X - x + 'px';
            elem.style.top = pagePos(ev).Y - y + 'px';
        }
    
        function mouseup(ev) {
            var ev = ev || window.event;
            removeEvent(document, 'mousemove', mousemove);
            removeEvent(document, 'mouseup', mouseup);
        }
    
    } 
    複製代碼
相關文章
相關標籤/搜索