欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS判斷鼠標(biāo)進(jìn)入容器的方向與window.open新窗口被攔截的問題

 更新時間:2016年12月23日 11:47:22   作者:SniffRose  
這篇文章主要給大家介紹了利用Javascript判斷鼠標(biāo)進(jìn)入容器方向的方法,以及window.open新窗口被攔截的問題分析,文中給出了詳細(xì)圖文介紹和示例代碼,相信對大家的理解和學(xué)習(xí)具有一定的參考借鑒價值,下面來一起看看吧。

一、鼠標(biāo)進(jìn)入容器方向的判定

判斷鼠標(biāo)從哪個方向進(jìn)入元素容器是一個經(jīng)常碰到的問題,如何來判斷呢?

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

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

如下圖所示:

以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誰小按誰進(jìn)行比例縮放**/
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 );

/** 根據(jù)X,Y的值,做反正切atan2計算,返回值在[-π,π]之間 ,這里加上180,剔除負(fù)值**/
/** 如果不加180,則0,1,2,3對應(yīng)下左上右**/
/** 除以90并四舍五入,使得可以以45度為分割線,獲取象限**/
/** 加3與4取模,將0,1,2,3對應(yīng)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公式比較難理解,首先得到鼠標(biāo)坐標(biāo)經(jīng)過換算后的值,然后算出該坐標(biāo)的弧度,接著換算成度數(shù),加180去掉負(fù)數(shù),隨后轉(zhuǎn)移象限將0123對應(yīng)TRBL,如果不加180去掉負(fù)數(shù),0123對應(yīng)BLTR,有點不合CSS的習(xí)慣。

第二種方法,利用斜率

如下圖所示:


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

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

$(".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坐標(biāo)都是負(fù)的
 }
 //0123對應(yīng)TRBL
});

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

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

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

新窗口被攔截檢測

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

如下代碼所示:

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('您阻止了窗口的打開。');

為何新窗口被攔截

瀏覽器設(shè)計者出于安全的考慮,window.open 命令在用戶操作(trusted events)時, 才會正常的打開應(yīng)該頁面而不會被瀏覽器攔截。什么是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.

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

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

如何Ajax回調(diào)中避免被攔截

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

如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>彈窗攔截測試</title>
 <style type="text/css">
 #btn{ width:100px; height: 30px; line-height: 30px; text-align:center; background-color:#0087dc; transition:all .2s; color:#fff; border-radius:3px;cursor:pointer; }
 #btn:hover{ background-color:#0060b2; }
 </style>
</head>
<body>
 <div id="btn">打開新窗口</div>
 <script type="text/javascript">
 btn.addEventListener('click',(e)=>{
  var xhr = new XMLHttpRequest();
  var newWin = window.open('about:blank');
  xhr.onreadystatechange = ()=>{
  if(xhr.readyState == 4){
   if(xhr.status == 200){
   newWin.location.;
   }
  }
  };
  xhr.open('post','/dnslookup',!1);//異步方式
  xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
  xhr.send('host=www.baidu.com&rrtype=A');
 },!0);
 </script>
</body>
</html>

服務(wù)端代碼如下:

var http = require('http'),
 url = require('url'),
 dns = require('dns'),
 qs = require('querystring'),
 fs = require('fs');

function router(req,res,pathname){
 switch(pathname){
 case '/dnslookup':
  lookup(req,res);
  break;
 default:
  showIndex(req,res);
 }
}
function showIndex(req,res){
 var pagePath = __dirname+'/'+'block.html';
 var html = fs.readFileSync(pagePath);
 res.end(html);
}
function lookup(req,res){
 var postData = '';
 req.on('data',function(data){
 postData+=data;
 });
 req.on('end',function(data){
 var json = qs.parse(postData);
 var hostname = json.host;
 var rrtype = json.rrtype;
 dns.resolve(hostname,rrtype,function(err,adresses){
  if(err){
  res.end(JSON.stringify({errcode:1,ips:[]}));
  }
  res.end(JSON.stringify({errcode:0,ips:adresses}));
 });
 
 });
}
http.createServer(function(req,res){
 var pathname = url.parse(req.url).pathname;
 req.setEncoding("utf8");
 res.writeHead(200,{'Content-Type':'text/html'});
 router(req,res,pathname);
}).listen(3000);

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

總結(jié)

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

相關(guān)文章

最新評論