国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JS判斷鼠標進入容器的方向與window.open新窗口被攔截的問題

2019-11-19 18:18:02
字體:
來源:轉載
供稿:網友

一、鼠標進入容器方向的判定

判斷鼠標從哪個方向進入元素容器是一個經常碰到的問題,如何來判斷呢?

首先想到的是:獲取鼠標的位置,然后經過一大堆的if..else邏輯來確定。這樣的做法比較繁瑣,下面介紹兩種比較方便的方法:

第一種方法,利用圓和反正切三角函數

如下圖所示:

以div容器的中心點作為圓心,以高和寬的最小值作為直徑畫圓,將圓以[π/4,3π/4),[3π/4,5π/4),[5π/4,7π/4),[-π/4,π/4)劃分為四個象限。

代碼如下:

$(".box").on("mouseenter mouseleave",function(e){/** 獲取容器寬高 **/var w = $(this).width();var h = $(this).height();/** 計算X和Y相對于圓心點的距離,如果不是正方形,按照X,Y誰小按誰進行比例縮放**/var x = (e.pageX - $(this).offset().left - (w/2)) * ( w > h ? (h/w) : 1 );var y = (e.pageY - $(this).offset().top - (h/2)) * ( h > w ? (w/h) : 1 );/** 根據X,Y的值,做反正切atan2計算,返回值在[-π,π]之間 ,這里加上180,剔除負值**//** 如果不加180,則0,1,2,3對應下左上右**//** 除以90并四舍五入,使得可以以45度為分割線,獲取象限**//** 加3與4取模,將0,1,2,3對應t,r,b,l既上右下左**/var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180 ) / 90 )+3)%4;switch(direction) { case 0: /** 上 **/ break; case 1: /** 右 **/ break; case 2: /** 下 **/ break; case 3: /** 左 **/ break;}});

這個方法中的Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180 )/90)+3)% 4公式比較難理解,首先得到鼠標坐標經過換算后的值,然后算出該坐標的弧度,接著換算成度數,加180去掉負數,隨后轉移象限將0123對應TRBL,如果不加180去掉負數,0123對應BLTR,有點不合CSS的習慣。

第二種方法,利用斜率

如下圖所示:


以瀏覽器左上角做原點,畫坐標軸,向下為負,向右為正,和數學坐標系一致。中間的div的左上角坐標(x1,y1),右下角坐標(x2,y2),中心點的坐標(cx,cy)。如圖兩點的斜率為k(k<0),關于x軸對稱的斜率為-k。

需要注意一點的是所有的Y軸坐標都是負數,因為就是將容器置于坐標系的第四象限。

$(".box").on("mouseenter mouseleave", function(e) { var w = $(this).width(); h = $(this).height(), x1 = $(this).offset().left, y1 = -$(this).offset().top, x2 = x1 + w, y2 = y1 - h, cx = (x1 + x2) / 2, cy = (y1 + y2) / 2, k = (y2 - y1) / (x2 - x1), k1 = (-e.pageY - cy) / (e.pageX - cx), direction = -1; if ((k1 < -k) && (k < k1)) { direction = e.pageX > cx?1:3; } else { direction = -e.pageY > cy?0:2;//大家理解代碼的時候一定記住,Y坐標都是負的 } //0123對應TRBL});

如上代碼所示:當鼠標的位置與容器中心點所形成的斜率在(k,-K)之間,必然是左右移入或移出,如果鼠標的X坐標大于中心點CX,則是右邊進入,否則為左邊進入;若斜率不在(k,-k)之間,則是上下進入或出去,只要判斷鼠標的Y坐標與中心點CY的大小關系即可,大于則是下邊,相反就是上邊。

二、window.open新窗口被攔截的問題

當我們使用window.open()方法打開一個窗口時,部分瀏覽器會檢測是否是用戶主動行為,若不是,則會阻止窗口的打開,例如在異步Ajax的回調函數中調用。

新窗口被攔截檢測

窗口被阻止打開,如不給出提示,用戶體驗將會很不好,那如何檢測窗口被阻止?

如下代碼所示:

var newWin = null, isBlock = !1;/** 新窗口被某些擴展阻止打開,會拋出錯誤,因此使用try..catch **/try { newWin = window.open('http://www.baidu.com', '_blank'); /** 新窗口被阻止時,返回值是undefined或null**/ (!newWin) && (isBlock = !0);} catch (ex) { isBlock = !0;}if (isBlock) alert('您阻止了窗口的打開。');

為何新窗口被攔截

瀏覽器設計者出于安全的考慮,window.open 命令在用戶操作(trusted events)時, 才會正常的打開應該頁面而不會被瀏覽器攔截。什么是trusted events?

The isTrusted read-only property of the Event interface is a boolean that is true when the event was generated by a user action, and false when the event was created or modified by a script or dispatched via dispatchEvent.

當前事件是由用戶行為觸發(例如鼠標點擊按鈕觸發操作),便是trusted events,而用自定義事件dispatchEvent觸發的事件則不是trusted events。

因此使用JS代碼自動觸發window.open() ,第二個參數不為_self,打開新窗口在大部分瀏覽器中會被攔截。如果第二個參數為_self,則不會被攔截,如window.open("

如何Ajax回調中避免被攔截

很多人的需求是點擊按鈕發送Ajax請求,請求數據回來后,再使用window.open來打開新的窗口,由于是異步操作,直接window.open ,肯定會被攔截。這時我們可以變通以下,先打開一個空窗口,然后等數據回來后替換為需要的地址

如下所示:

服務端代碼如下:

如上所示便可解決在Ajax回調中新窗口被攔截的問題。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 柘城县| 定陶县| 兰西县| 崇明县| 原阳县| 华宁县| 中山市| 游戏| 娄底市| 额尔古纳市| 元朗区| 诸暨市| 涞源县| 烟台市| 施秉县| 德格县| 宾阳县| 甘肃省| 钦州市| 南乐县| 瓮安县| 吴桥县| 祁门县| 临沂市| 浮山县| 西畴县| 泰兴市| 从江县| 蒙城县| 宣威市| 南华县| 肃南| 前郭尔| 台州市| 个旧市| 育儿| 迭部县| 和顺县| 娄底市| 江油市| 扎囊县|