javascript动画系列第二篇——磁性吸附

×

目录

[1]范围限定 [2]拖拽范围 [3]磁性吸附

前面的话

  上一篇,我们介绍了元素拖拽的实现。但在实际应用中,常常需要为拖拽的元素限定范围。而通过限定范围,再增加一些辅助的措施,就可以实现磁性吸附的效果

范围限定

  如果我们限定元素只可以在可视范围内移动,那么就需要对其进行范围限定

  首先,先要搞清楚是可视区域限定被拖拽元素

  左侧范围L0 = 0

  右侧范围R0 = document.documentElement.clientWidth

  上侧范围T0 = 0

  下侧范围B0 = document.documentElement.clientHeight

  元素的上下左右四边分别为

  左侧边 L = offsetLeft

  右侧边 R = offsetLeft + offsetWidth

  上侧边 T = offsetTop

  下侧边 B = offsetTop + offsetHeight

function limitedRange(obj,fn){
    var L0 = 0;
    var R0 = document.documentElement.clientWidth;
    var T0 = 0;
    var B0 = document.documentElement.clientHeight;
    var L = obj.offsetLeft;
    var R = obj.offsetLeft + obj.offsetWidth;
    var T = obj.offsetTop;
    var B = obj.offsetTop + obj.offsetHeight;

    if(L >= L0 && R <= R0 && T >= T0 && B <= B0){
        fn(obj);
    }
}

拖拽范围

  如果将范围限定用在拖拽元素上,则需要一些改变

  首先,限定条件并不是在范围内执行什么,而是不在范围内时,应该执行什么

  由于在拖拽实现中,已经获取了元素距离可视区域左上角的X轴和Y轴的距离,所以不需要再通过offsetLeft和offsetTop进行重新获取

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">测试文字</div>
<script>
function drag(obj){
    obj.onmousedown = function(e){
        e = e || event;
        //获取元素距离定位父级的x轴及y轴距离
        var x0 = this.offsetLeft;
        var y0 = this.offsetTop;
        //获取此时鼠标距离视口左上角的x轴及y轴距离
        var x1 = e.clientX;
        var y1 = e.clientY;
        //鼠标按下时,获得此时的页面区域
        var L0 = 0;
        var R0 = document.documentElement.clientWidth;
        var T0 = 0;
        var B0 = document.documentElement.clientHeight;
        //鼠标按下时,获得此时的元素宽高
        var EH = obj.offsetHeight;
        var EW = obj.offsetWidth;
        document.onmousemove = function(e){
            e = e || event;
            //获取此时鼠标距离视口左上角的x轴及y轴距离
            x2 = e.clientX;
            y2 = e.clientY;
            //计算此时元素应该距离视口左上角的x轴及y轴距离
            var X = x0 + (x2 - x1);
            var Y = y0 + (y2 - y1);
            /******范围限定*******/
            //获取鼠标移动时元素四边的瞬时值
            var L = X;
            var R = X + EW;
            var T = Y;
            var B = Y + EH;
            //在将X和Y赋值给left和top之前,进行范围限定
            //只有在范围内时,才进行相应的移动
            //如果脱离左侧范围,则left置L0
            if(L < L0){X = L0;}
            //如果脱离右侧范围,则left置为R0
            if(R > R0){X = R0 - EW;}
            //如果脱离上侧范围,则top置T0
            if(T < T0){Y = T0;}
            //如果脱离下侧范围,则top置为B0
            if(B > B0){Y = B0 - EH;}
            obj.style.left = X + ‘px‘;
            obj.style.top = Y + ‘px‘;
        }

        document.onmouseup = function(e){
            //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
            document.onmousemove = null;
            //释放全局捕获
            if(obj.releaseCapture){
                obj.releaseCapture();
            }
        }
        //阻止默认行为
        return false;
        //IE8-浏览器阻止默认行为
        if(obj.setCapture){
            obj.setCapture();
        }
    }
}
drag(test);
</script>    

磁性吸附

  磁性吸附只需要在范围限定的基础上,做一些修改即可

  下列代码中,只要元素的四边,距离可视区域范围的四边小于50px,则元素将直接吸附对应的边上

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">测试文字</div>
<script>
function drag(obj){
    obj.onmousedown = function(e){
        e = e || event;
        //获取元素距离定位父级的x轴及y轴距离
        var x0 = this.offsetLeft;
        var y0 = this.offsetTop;
        //获取此时鼠标距离视口左上角的x轴及y轴距离
        var x1 = e.clientX;
        var y1 = e.clientY;
        //鼠标按下时,获得此时的页面区域
        var L0 = 0;
        var R0 = document.documentElement.clientWidth;
        var T0 = 0;
        var B0 = document.documentElement.clientHeight;
        //鼠标按下时,获得此时的元素宽高
        var EH = obj.offsetHeight;
        var EW = obj.offsetWidth;
        document.onmousemove = function(e){
            e = e || event;
            //获取此时鼠标距离视口左上角的x轴及y轴距离
            x2 = e.clientX;
            y2 = e.clientY;
            //计算此时元素应该距离视口左上角的x轴及y轴距离
            var X = x0 + (x2 - x1);
            var Y = y0 + (y2 - y1);

            /******磁性吸附*******/
            //获取鼠标移动时元素四边的瞬时值
            var L = X;
            var R = X + EW;
            var T = Y;
            var B = Y + EH;
            //在将X和Y赋值给left和top之前,进行范围限定
            //只有在范围内时,才进行相应的移动
            //如果到达左侧的吸附范围,则left置L0
            if(L - L0 < 50){X = L0;}
            //如果到达右侧的吸附范围,则left置为R0
            if(R0 - R < 50){X = R0 - EW;}
            //如果到达上侧的吸附范围,则top置T0
            if(T - T0 < 50){Y = T0;}
            //如果到达右侧的吸附范围,则top置为B0
            if(B0 - B < 50){Y = B0 - EH;}
            obj.style.left = X + ‘px‘;
            obj.style.top = Y + ‘px‘;
        }

        document.onmouseup = function(e){
            //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
            document.onmousemove = null;
            //释放全局捕获
            if(obj.releaseCapture){
                obj.releaseCapture();
            }
        }
        //阻止默认行为
        return false;
        //IE8-浏览器阻止默认行为
        if(obj.setCapture){
            obj.setCapture();
        }
    }
}
drag(test);
</script>    
时间: 2024-10-11 12:40:15

javascript动画系列第二篇——磁性吸附的相关文章

深入理解javascript作用域系列第二篇——词法作用域和动态作用域

× 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作模型导致的,作用域分为词法作用域和动态作用域,分清这两种作用域模型就能够对变量查找过程有清晰的认识.本文是深入理解javascript作用域系列第二篇——词法作用域和动态作用域 词法作用域 第一篇介绍过,编译器的第一个工作阶段叫作分词,就是把由字符组成的字符串分解成

javascript动画系列第一篇——模拟拖拽

× 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容性问题,以及功能实现的方式,用的不是很广泛.javascript动画广泛使用的还是模拟拖拽.本文将详细介绍该内容 原理介绍 模拟拖拽最终效果和在桌面上移动文件夹的效果类似 鼠标按下时,拖拽开始.鼠标移动时,被拖拽元素跟着鼠标一起移动.鼠标抬起时,拖拽结束 所以,拖拽的重点是确定被拖拽元素是如何移动的

深入理解javascript对象系列第二篇——属性操作

× 目录 [1]查询 [2]设置 [3]删除[4]继承 前面的话 对于对象来说,属性操作是绕不开的话题.类似于“增删改查”的基本操作,属性操作分为属性查询.属性设置.属性删除,还包括属性继承.本文是对象系列的第二篇——属性操作 属性查询 属性查询一般有两种方法,包括点运算符和方括号运算符 var o = { p: 'Hello World' }; o.p // "Hello World" o['p'] // "Hello World" [注意]变量中可以存在中文,因

javascript面向对象系列第二篇——创建对象的5种模式

× 目录 [1]字面量 [2]工厂模式 [3]构造函数[4]原型模式[5]组合模式 前面的话 如何创建对象,或者说如何更优雅的创建对象,一直是一个津津乐道的话题.本文将从最简单的创建对象的方式入手,逐步介绍5种创建对象的模式 [1]对象字面量 一般地,我们创建一个对象会使用对象字面量的形式 [注意]有三种方式来创建对象,包括new构造函数.对象直接量和Object.create()函数,详细情况移步至此 var person1 = { name: "bai", age : 29, jo

EnjoyingSoft之Mule ESB基础系列第二篇:Mule ESB基本概念

目录 1. 使用Anypoint Studio开发 2. Mule ESB Application Structure - Mule ESB应用程序结构 3. Mule ESB Application整体构造 4. Mule ESB构造元素 - Flow 5. Mule ESB构造元素 - Connector 6. Mule ESB构造元素 - Processor Mule ESB在众多开源的ESB中处于领先者的地位,MuleSoft公司也作为独角兽,2017年在纽交所上市.我们作为MuleSo

ansible系列第二篇(模块使用)

ansible系列第二篇(模块使用) 模块使用 设置ansible提权 在hosts文件加入sudo提权的密码: 18.18.23.102 ansible_become_pass='passwd' 执行: ansible test -S -R root -m shell -a "ls -l /" 查看ansible有那些模块: ansible-doc -l 获取各个模块详细帮助信息 ansible-doc -s ping ping模块: ansible test -m ping 从受控

javascript动画系列第三篇——碰撞检测

前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多,接下来使用九宫格分析法 假设黄色元素要与红色元素进行碰撞.将红色元素所处的区域分为9部分,自身处于第9部分,周围还存在8个部分.只要黄色元素进入红色元素的第9部分,就算碰撞.否则,都算未碰撞 总共分为以下5种情况: 1.处于上侧未碰撞区域——1.2.3区域 2.处于右侧未碰撞区域——3.4.5区域

Android Metro风格的Launcher开发系列第二篇

前言: 各位小伙伴们请原谅我隔了这么久才开始写这一系列的第二篇博客,没办法忙新产品发布,好了废话不说了,先回顾一下:在我的上一篇博客Android Metro风格的Launcher开发系列第一篇写了如何配置Android开发环境,只是用文字和图片展示了开发Metro风格Launcher的初步设计和产品要求,这一篇文章将会从代码上讲解如何实现对应的UI效果,好了,评书开讲! Launcher主体框架实现: Launcher主体框架我选用的是大家所熟悉的ViewPager控件,因为ViewPager

【转载】Android Metro风格的Launcher开发系列第二篇

前言: 各位小伙伴们请原谅我隔了这么久才开始写这一系列的第二篇博客,没办法忙新产品发布,好了废话不说了,先回顾一下:在我的上一篇博客Android Metro风格的Launcher开发系列第一篇写了如何配置Android开发环境,只是用文字和图片展示了开发Metro风格Launcher的初步设计和产品要求,这一篇文章将会从代码上讲解如何实现对应的UI效果,好了,评书开讲! Launcher主体框架实现: Launcher主体框架我选用的是大家所熟悉的ViewPager控件,因为ViewPager