范围内的拖拽事件

 <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            height: 5000px;
        }

        .box {
             800px;
            height: 800px;
            border: 10px solid #000;
            margin: 30px auto;
            position: relative;
        }

        .inner {
             100px;
            height: 100px;
            background: pink;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div class="box">
        <div class="inner"></div>
    </div>

    <script src="./tools.js"></script>
    <script>
        // 粉色div在 父级div 范围内拖拽,不能移动出div范围

        // 1,先实现拖拽

        // 获取标签对象
        var oBox = document.querySelector('.box');
        var oInner = document.querySelector('.inner');

        // 获取父级标签,margin-left 和 border-left 占位
        // 当前不是通过 style 获取样式属性
        // 是通过 getComputedStyle 获取样式属性
        // 支持 marginLeft  和  margin-left 

        // margin-left 属性值
        var ml = parseInt(myGetStyle(oBox, 'margin-left'));
        // margin-top 属性值
        var mt = parseInt(myGetStyle(oBox, 'marginTop'));

        // border-left-width 宽度
        var bl = parseInt(myGetStyle(oBox, 'border-left-width'));
        // border-top-width 宽度
        var bt = parseInt(myGetStyle(oBox, 'border-top-width'));

        // 获取inner, div标签的相关数据
        var hs = oInner.offsetHeight;
        var ws = oInner.offsetWidth;

        // 获取oBox, div标签的相关数据
        var hf = oBox.clientHeight;
        var wf = oBox.clientWidth;

        // 鼠标按下,给鼠标移动添加 事件处理函数
        oInner.addEventListener('mousedown', function () {
            document.addEventListener('mousemove', myMove);
        })

        // 鼠标抬起,给鼠标移动删除 事件处理函数
        document.addEventListener('mouseup', function () {
            document.removeEventListener('mousemove', myMove);
        })



        function myMove(e) {
            e = e || window.event;
            // 获取的是页面左上角到鼠标的定位
            var t = e.pageY;
            var l = e.pageX;

            // 赋值时,left 定位需要减去 父级元素  左侧margin-left占位  左侧边框线占位
            // 赋值时,top  定位需要减去 父级元素  上侧margin-top占位  上侧边框线占位
            // 如果需要div中心位置和鼠标位置重合
            // 需要减去占位的一半

            t =  t - mt - bt - hs/2;
            l =  l - ml - bl - ws/2;

            // 设定极值范围
            // 最小值坐标就是 0  0  不能是负数
            // 最大值坐标就是 父级div宽高 - 子级div宽高

            if(t < 0){
                t = 0;
            }

            if(l < 0){
                l = 0;
            }

            if(t > hf - hs){
                t = hf - hs;
            }

            if(l > wf - ws){
                l = wf - ws;
            }
            oInner.style.top = t  +  'px';
            oInner.style.left = l  + 'px';
        }


        // 总结:
        // 1,因为页面有可能滚动,获取的数据必须是针对页面的坐标
        //   获取鼠标坐标,需要是 e.pageX  e.pageY

        // 2,需要提前获取到标签的相关数据
        //   父级 : 内容(宽高) + padding 的占位
        //          左 上 的 margin 和 border 占位 
        //   子级 : 内容(宽高) + padding + border 的占位
        //          内容(宽高) + padding 的占位
        //   最好定义在 函数值外,先获取好数据

        // 3, 除了 触发 鼠标按下事件效果,必须在 inner,div 范围内
        //    其他 事件的触发,都有可能在 inner,div范围外,必须要给 document 做绑定

        // 4, mousemove 必须以函数名称的形式,绑定事件处理函数
        //    当 鼠标抬起时,才能执行删除事件处理函数

        // 5, left定位数值 : 
        //        鼠标坐标 - oBox,div的左外边距 - oBox,div的左边框宽度 - inner,div宽度的一半

        // 6, top定位数值:
        //        鼠标坐标 - oBox,div的上外边距 - oBox,div的上边框宽度 - inner,div高度的一半

        // 7, 设定极值:
        //        当前定位使用的是绝对定位 absolute
        //    最小值 : 0   0
        //    最大值 : oBox,div,内容(宽高)+padding占位 - oInner,div, 内容(宽高)+padding+border占位   
 
 
  获取鼠标的坐标, offset   client  page

            offset : 拖拽时,因为坐标原点的改变,造成div,来回闪烁
                     点击时可以使用

            client : div 使用 fixed 固定定位时 , 使用 client
                     都是 视窗窗口的左上角

            page   :div 使用 absolute 绝对定位
                     定位原点的左上角是 父级标签的左上角
                     与视窗窗口的左上角不一定重合
                     只能使用 page 坐标
右侧打赏一下 代码改变世界一块二块也是爱
原文地址:https://www.cnblogs.com/ht955/p/14083764.html