资讯专栏INFORMATION COLUMN

js判断鼠标进入容器的方向小解

fantix / 1884人阅读

摘要:有不对的地方,或者有更好的理解,请告诉我,谢谢原理以容器的中心点作为圆心,以高和宽的最小值作为直径画圆,将圆以,,,,,,,划分为四个象限,鼠标进入容器时的点的值在这四个象限里分别对应容器边框的下,右,上,左。

$("#wrap").bind("mouseenter mouseleave",function(e) {
    var w = $(this).width();
    var h = $(this).height();
    var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
    var y = (e.pageY - this.offsetTop - (h / 2)) * (h > w ? (w / h) : 1);
    var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4; //direction的值为“0,1,2,3”分别对应着“上,右,下,左”
    var eventType = e.type;
    var dirName = new Array("上方","右侧","下方","左侧");
    if(e.type == "mouseenter"){
        $("#result").html(dirName[direction]+"进入");
    } else {
        $("#result").html(dirName[direction]+"离开");
    }
});

就这么几行代码,将我印象里会有一长串的if else或者switch来完成的事完美的解决掉。在感到神奇之后,更多的是不解,因为看不懂。在网上搜索一番,也没有找到有谁来分析这个算法。于是自己研究了一下,现在写下来,作为自己的一份学习笔记,也希望能够和大家分享。

有不对的地方,或者有更好的理解,请告诉我,谢谢!

原理:以div容器的中心点作为圆心,以高和宽的最小值作为直径画圆,将圆以[π/4,3π/4),[3π/4,5π/4),[5π/4,7π/4),[-π/4,π/4)划分为四个象限,鼠标进入容器时的点的atan2(y,x)值在这四个象限里分别对应容器边框的下,右,上,左。如下图所示

var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);

计算x坐标值时,如果点原来的x坐标的绝对值大于圆的半径值,则按 h/w 这个比例进行缩小,使得到的点的位置在容器的边界位置所对应的象限区间里。 y 坐标的计算也是一样。

var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;

((Math.atan2(y, x) * (180 / Math.PI)将点的坐标对应的弧度值换算成角度度数值,这里加上180并非必要,只是为了使得到的0,1,2,3能够与习惯性的上,右,下,左的位置对照,如果不加上180,得到的0,1,2,3就会分别对应下,右,上,左。
*修正:这里加上180不是并非必要的,而是在这个算法里必须的,因为atan2(y,x)返回值的范围是[-π,π],而不是我们习惯的[0,2π],负值会影响结果的正确性(比如右上和右下算出来的结果会不同),而且确实也使得得到的结果0,1,2,3的顺序符合了习惯(原作者可能没想这个,只是css里总是这个顺序,或许是我自己的习惯~)。

除以90,再取四舍五入值,是一个很精妙的用法,使得可以以45°为分界线。

分析完这个算法后,我内心有些激动。这里并没有用到什么高深的知识,即使是三角函数的基础知识都可以不知道(虽然初中就学了),但是可以用这么短短的三两行代码,就把我脑袋里浮现的那一长串的if else抛向云和山的彼端去,真的让我很难抑制内心的激动,深深的体会到算法之美,数学之美。

来源:http://sentsin.com/web/112.html
相关参考文档:http://www.cnblogs.com/lyzg/p...
代码参考: https://github.com/liuyunzhug...

最后感谢两位大牛的总结

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80187.html

相关文章

  •  用js实现点击切换和自动播放轮播图示例

      js实现点击切换和自动播放的轮播图,其实十分简单,话不多说,我们直接看示例:  轮播图案例  <!DOCTYPEhtml>   <html>   <head>   <metacharset="UTF-8">   <metaname="vie...

    3403771864 评论0 收藏0
  • 事件代理及常用 HTML 事件

    摘要:之前总结了事件捕获和冒泡以及阻止事件传播,今天写一下事件代理方面的总结事件之捕获冒泡阻止事件传播事件代理监听列表中多项时,实现点击控制台打印对应文本,如下苹果香蕉葡萄首先想到的对每一个进行监听或者使用和的区别是属性,是方法。 之前总结了事件捕获和冒泡以及阻止事件传播,今天写一下事件代理方面的总结DOM 事件之捕获、冒泡:阻止事件传播: 事件代理 监听列表中多项 li 时,实现点击 li...

    xavier 评论0 收藏0
  • 原生js练习题---第四课

    摘要:然而问题是,这个法则在导航条的主体是可行的但是子选单因为前面提到的三层嵌套构造圆角,已经无法减少嵌套了,同时还得考虑到子选单也是嵌套在导航条里的啊。。。同理,反过来进入子选单时自然就用来抵消达到筛选的目的。 0x1setTimeout应用 实现效果:4-01setTimeout应用 又见导航条,先看下css,这里用的是雪碧图背景做出圆角的效果,虽然是经典的方法、兼容性好,但这种代码写起...

    Snailclimb 评论0 收藏0
  • 用 ES6 写全屏滚动插件

    摘要:这篇文章将介绍如何使用原生主要使用语法实现全屏滚动插件,兼容手机触屏,触摸板优化,支持自定义页面动画,压缩后文件只有。 这篇文章将介绍如何使用原生 JS (主要使用 ES6 语法)实现全屏滚动插件,兼容 IE 10+、手机触屏,Mac 触摸板优化,支持自定义页面动画,压缩后 gzip 文件只有 2.15KB。完整源码在这 pure-full-page,点这查看 demo。 1)前面的话...

    liuchengxu 评论0 收藏0
  • 一步步实现nest粒子特效

    摘要:尝试实现画出一个弹射的小球很简单,那怎么用多个小球实现这样的效果呢。 本文首发于我的博客,这是我的github,欢迎star。   这篇博客是模仿nest.js实现一个demo,由简单到复杂,来一步步的实现它。这里是效果预览。我的github里边还有很多别的前端的demo,喜欢的话可以点个star,你的支持就是我的动力。 从一道面试题开始 实现一个半径10px的小球在500px*5...

    ky0ncheng 评论0 收藏0

发表评论

0条评论

fantix

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<