2023-03-21_DOMDAY07-鼠标拖拽

1. 获取样式

1.1 JS获取style中的样式

DOM对象 是不可以直接获取内部样式的中属性的
      只能获取行内样式的属性

1.2 client系列 (只读)

  • clientWidth 拿的是盒子 内容 + padding的宽
  • clientHeight 拿的是盒子 内容 + padding的高
  • clientLeft 拿的是盒子左边框大小
  • clientTop 拿的是盒子上边框大小

1.3 offset系列 (只读)

  • offsetWidth
    • 拿的是盒子 内容 + padding + border的宽
  • offsetHeight
    • 拿的是盒子 内容 + padding + border的高
  • offsetLeft
    • 拿的是元素的偏移量:可以认为就是拿的绝对定位left值
    • 切记如果进行 offsetLeft 的值进行加法运算不允许添加px
  • offsetTop
    • 拿的是元素的偏移量:可以认为就是拿的绝对定位top值
  • 在没有边框的时候
    那么 clientWidth/offsetWidthclientHeight/offsetHeight 是一样的结果

1.4 Scroll系列

  • scrollWidth 只读
    • 当内容比盒子小的时候,拿的是盒子的clientWidth
    • 当内容比盒子大的时候,拿的是内容的offsetWidth + 盒子的一侧内边距
    • document.documentElement.scrollWidth
  • scrollHeight 只读
    • 当内容比盒子小的时候,拿的是盒子的clientHeight
    • 当内容比盒子大的时候,拿的是内容的offsetHeight + 盒子的一侧内边距
    • document.documentElement.scrollHeight
  • scrollTop可读可写
    • 拿的是盒子内容向上滚动的距离
    • document.documentElement.scrollTop
  • scrollLeft可读可写
    • 拿的是盒子内容向左滚动的距离
    • document.documentElement.scrollLeft

1.5 总结

  1. 元素的大小:宽和高的获取:以后我们拿元素的宽和高,先看元素有没有边框,如果没有边框,那么clientWidth和offsetWidth是一样的,如果有边框,看你需要不,需要的话就用offsetWidth,不需要就用clientWidth; scrollWidth几乎不用
  2. 元素的位置(偏移量)的获取:以后需要获取元素的位置直接通过offsetLeftoffsetTop 去获取,但是注意相对的参照元素是谁;(和绝对定位参照类似)
  3. 视口宽高求法(固定的)
    • document.documentElement.clientWidth
    • document.documentElement.clientHeight
  • 案例练习---滚动页面导航栏固定
<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <title>案例练习-导航栏跟随</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            div {
                width: 100%;
                height: 150px;
                background-color: #e6e1e2;
                text-align: center;
                line-height: 150px;
            }
            div input {
                width: 735px;
                height: 40px;
                border-radius: 20px;
                border: 2px solid #f40;
                outline: none;
            }
        </style>
    </head>
    <body style="height: 3000px;">
        <div>
            <input type="text">
        </div>
        <script>
            // 滚动一个视口的高度 然后就将input固定在头部
            // 如果不到一个视口的高度 就默认了
            var inp = document.querySelector('input')
            document.onscroll = function() {
                // 获取的是html滚动的距离
                var scrollHeight = document.documentElement.scrollTop;
                // 获取的视口
                var htmlDis = document.documentElement.clientHeight;
                if (scrollHeight >= htmlDis) {
                    inp.style.position = 'fixed'
                    inp.style.top = 0
                    inp.style.left = 0
                    inp.style.right = 0
                    inp.style.margin = 'auto'
                } else {
                    inp.style.position = 'static'
                }
            }
        </script>
    </body>
</html>
  • 案例练习-盒子来回移动
<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <title>案例练习-盒子来回移动</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            div {
                position: absolute;
                width: 100px;
                height: 100px;
                background-color: aquamarine;
            }
        </style>
    </head>
    <body>
        <div></div>

        <script>
            var div = document.querySelector('div');
            var step = 3;
            setInterval(function(){
                var startX = div.offsetLeft;
                var endX = startX + step;

                // 边界右:
                if(endX >= document.documentElement.clientWidth - div.offsetWidth){
                    endX = document.documentElement.clientWidth - div.clientWidth;
                    step = -3;
                // 左边界:
                }else if(endX <= 0){
                    endX = 0;
                    step = 3;
                }
                div.style.left = endX + 'px';
            },16);
        </script>
    </body>
</html>

2. 初始包含块

  • 即页面的第一屏
  • 初始包含块:和浏览器第一屏大小一致的一个块状结构,称作初始包含块,元素子绝父不相的时候,其实相对的是初始包含块去做的定位,不是body也不是html也不是视口
  • 打开浏览器最外层的结构,首先是document,接着是初始包含块 , HTML , body
  • html单独设置某些特殊属性作用的位置(background-color)
  • body单独设置某些特殊属性作用的位置(background-color)
  • html, body 比较特殊,特殊原因它的部分属性作用的不是自己 而是document,doucument是网页最外层的元素,html文档当中没有任何标签标示它
  • 如果同时设置, 即body生效 html还是作用于document
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }   
            html{
                width: 500px;
                height: 500px;
                margin-left: 100px;
                border: 10px solid blue;
                /* background-color: red; */ /* 整个网页变成红色而不是宽高500的这个盒子*/
                /*html比较特殊,特殊原因它的部分属性作用的不是自己 而是document*/
                /*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
            }
            body{
                width: 300px;
                height: 3000px;
                border: 10px solid yellow;
                background-color: red;/* 整个网页变成红色而不是宽高500的这个盒子*/
                /*body比较特殊,单独的给Body设置某些属性,作用的不是自己 而是document*/
                /*doucument是网页最外层的元素,html文档当中没有任何标签表示它*/
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
    </body>
</html>

3. 系统滚动条的控制

   html和body这两个元素overflow的scroll属性,控制着系统的滚动条,系统的滚动条有两个,一个是body身上的,一个是document身上的。我们平时看到的那个滚动条是document身上的。如果我们想要控制系统滚动条哪个显示哪个关闭分以下情况:

  • 单独的给body或者html 设置overflow:scroll 滚动条打开的全部都是document的
  • 如果两个元素同时设置overflow属性,body设置的是scroll,html设置是hidden,那么document的滚动条被关闭,body身上的滚动条会打开,相反,body身上被关闭,document身上的被打开
  • 如果两个元素同时设置overflow:hidden;那么系统的两个滚动条全部被关闭
  • 如果两个都设置overflow:scroll,那么html会打开document身上的,而body会打开自己身上的滚动条
  • 通常情况下系统滚动条会被禁用因为浏览器样式不统一
    企业级开发的书写方式 :
    html,body {
      height: 100%;
      overflow: hidden;
    }

4. 鼠标拖拽基础

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            #box{
                position: absolute;
                left: 0;
                top: 0;
                width: 150px;
                height: 80px;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
    <script type="text/javascript">
        window.onload = function(){
        var box = document.getElementById('box');
                
        box.onmousedown = function(e){
            e = e || window.event;
            //按下的时候获取元素的初始位置和鼠标的初始位置
            var eleX = box.offsetLeft;
            var eleY = box.offsetTop;
                    
            var startX = e.clientX;
            var startY = e.clientY;
                    
            box.onmousemove = function(e){
                e = e || window.event;
                //可以获取鼠标的结束位置
                var endX = e.clientX;
                var endY = e.clientY;
                //求出鼠标的距离差 即 盒子的移动距离
                var disX = endX - startX;
                var disY = endY - startY;
                //求出元素移动的最终位置  = 元素的初始位置  + 鼠标的距离差(盒子的移动距离)
                var lastX = eleX + disX;
                var lastY = eleY + disY;
                //把求出来的最终位置设置给元素
                box.style.left = lastX + 'px';
                box.style.top = lastY + 'px';
            };
            box.onmouseup = function(){
                box.onmousemove = box.onmouseup = null;
            }           
        }       
    }
        </script>
    </body>
</html>
基础拖拽问题:
  • 鼠标拖动过快,会跑出元素,元素就不动
      因为计算机跟不上你的速度,跑出盒子,盒子不动,因为事件添加在盒子身上,跑出去后事件就不在盒子身上触发了。包括在外部鼠标抬起,也是解绑不了盒子上的事件的,因为鼠标抬起也是在盒子身上添加的;解决:移动事件和抬起事件,最好添加给document
浏览器默认行为:
  • 在盒子当中写上文字,拖拽先选中文字,在拖拽,文字跟着走,盒子不动,放手盒子会瞬间到放手的位置
    因为浏览器有默认行为,拖拽文字就是一个默认行为。
    解决:取消浏览器的默认行为

  • 在低版本浏览器当中在盒子当中写上文字,拖拽先选中文字,在拖拽会出现禁止拖拽的现象
      因为低版本浏览器专门有这样的行为,禁止拖拽是低版本浏览器专属,解决:使用全局捕获,把鼠标后续的事件,强制拉回作用在元素身上,以后鼠标就只能作用在元素身上了,全局捕获有捕获就有释放,否则后果自负

取消浏览器默认行为根据事件添加方式不同而不同

  • dom0事件,那么在事件回调当中写上return false;
  • dom2事件, 在事件回调当中添加e.preventDefault();
上下边界吸附效果
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title></title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            #box {
                position: absolute;
                left: 0;
                top: 0;
                width: 150px;
                height: 80px;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div id="box">张三</div>

        <script type="text/javascript">
            window.onload = function () {
                var box = document.getElementById('box');
                box.onmousedown = function (e) {
                    e = e || window.event;
                    //按下的时候获取元素的初始位置和鼠标的初始位置
                    var eleX = box.offsetLeft;
                    var eleY = box.offsetTop;
                    var startX = e.clientX;
                    var startY = e.clientY;
                    //全局捕获
                    box.setCapture && box.setCapture(); //只有低版本浏览器才会用到全局捕获
                    document.onmousemove = function (e) {
                        e = e || window.event;
                        //可以获取鼠标的结束位置
                        var endX = e.clientX;
                        var endY = e.clientY;
                        //求出鼠标的距离差
                        var disX = endX - startX;
                        var disY = endY - startY;
                        //求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
                        var lastX = eleX + disX;
                        var lastY = eleY + disY;



                        // 左右边界
                        // if(lastX >= document.documentElement.clientWidth - div.offsetWidth){
                        //     lastX = document.documentElement.clientWidth - div.clientWidth;
                        // }else if(lastX <= 0){
                        //     lastX = 0;
                        // }

                        // 上下边界
                        // if(lastY >= document.documentElement.clientHeight - div.clientHeight){
                        //     lastY = document.documentElement.clientHeight - div.offsetHeight;
                        // }else if(lastY <= 0){
                        //     lastY = 0;
                        // }

                        // 左右吸附效果
                        if(lastX >= document.documentElement.clientWidth - div.offsetWidth - 50){
                            lastX = document.documentElement.clientWidth - div.clientWidth;
                        }else if(lastX <= 50){
                            lastX = 0;
                        }
                        // 上下吸附效果
                        if(lastY >= document.documentElement.clientHeight - div.clientHeight - 50){
                            lastY = document.documentElement.clientHeight - div.offsetHeight;
                        }else if(lastY <= 50){
                            lastY = 0;
                        } 

                        //把求出来的最终位置设置给元素
                        box.style.left = lastX + 'px';
                        box.style.top = lastY + 'px';
                    };
                    document.onmouseup = function () {
                        document.onmousemove = document.onmouseup = null;
                        box.releaseCapture && box.releaseCapture(); //低版本浏览器释放全局捕获
                    };
                    return false;
                };
            };
        </script>
    </body>
</html>
  • 案例练习---碰撞变化效果
<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <title>21_鼠标拖拽-碰撞效果</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            div {
                position: absolute;
                width: 100px;
                height: 100px;
                background-color: aquamarine;
            }

            img {
                position: absolute;
                left: 0;
                top: 0;
                right: 0;
                bottom: 0;
                margin: auto;
                width: 100px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <div></div>
        <img src="./img/1.jpg">

        <script>
            var div = document.querySelector('div');
            var img = document.querySelector('img');

            div.onmousedown = function(event){
                var eleX = div.offsetLeft;
                var eleY = div.offsetTop;

                var startX = event.clientX;
                var startY = event.clientY;

                document.onmousemove = function(event){
                    var endX = event.clientX;
                    var endY = event.clientY;

                    var disX = endX - startX;
                    var disY = endY - startY;

                    var lastX = disX + eleX;
                    var lastY = disY + eleY;

                    // 左右边界
                    if(lastX >= document.documentElement.clientWidth - div.offsetWidth){
                        lastX = document.documentElement.clientWidth - div.clientWidth;
                    }else if(lastX <= 0){
                        lastX = 0;
                    }

                    // 上下边界
                    if(lastY >= document.documentElement.clientHeight - div.clientHeight){
                        lastY = document.documentElement.clientHeight - div.offsetHeight;
                    }else if(lastY <= 0){
                        lastY = 0;
                    }

                    div.style.left = lastX + 'px';
                    div.style.top = lastY + 'px';

                    // 碰撞效果
                    // 左
                    var divL = div.offsetLeft + div.offsetWidth;
                    var imgL = img.offsetLeft;

                    // 上
                    var divT = div.offsetTop + div.offsetHeight;
                    var imgT = img.offsetTop;

                    // 右
                    var divR = div.offsetLeft;
                    var imgR = img.offsetLeft + img.offsetWidth;

                    // 下
                    var divB = div.offsetTop;
                    var imgB = img.offsetTop + img.offsetHeight;

                    // 不换的
                    if(divL < imgL || divT < imgT || divR > imgR || divB > imgB){
                        img.src = './img/1.jpg';
                    }else {
                        img.src = './img/2.jpg';
                    }
                }
                document.onmouseup = function(){
                    document.onmouseup = document.onmousemove = null;
                }
            }
        </script>
    </body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。