前端筆記知識點整合之JavaScript(十一)event&BOM&滑鼠/盒子位置&拖拽/滾輪

来源:https://www.cnblogs.com/rope/archive/2019/03/29/10610260.html
-Advertisement-
Play Games

一、事件對象event 1.1 preventdefault()和returnValue阻止預設事件 通知瀏覽器不要執行與事件關聯的預設動作。 preventdefault() 支持Chrome等高級瀏覽器 returnValue 支持IE6、7、8 1.2 stopPropagation()和ca ...


一、事件對象event

1.1 preventdefault()returnValue阻止預設事件

通知瀏覽器不要執行與事件關聯的預設動作。

preventdefault()  支持Chrome等高級瀏覽器

returnValue     支持IE678

var box = document.getElementById('box');
var i = 0;
//滑鼠在box盒子滾動時觸發
box.onmousewheel = function(event){
   var event = event || window.event;
   //能力檢測,阻止預設事件
   if(event.preventDefault){
       event.preventDefault();
   }else{
       event.returnValue = true;
   }
   this.innerHTML = '你在我身上滾動了!' + i++;
}

1.2 stopPropagation()cancelBubble阻止事件繼續傳播

stopPropagation()    支持Chrome等高級瀏覽器

cancelBubble       支持IE678

var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var box3 = document.getElementById('box3');
box1.onclick = function(){
   alert('box1');
}
box2.onclick = function(event){
   alert('box2');
   //阻止事件繼續傳播,能力檢測
   if(event.stopPropagation){
       event.stopPropagation();
   }else{
       event.cancelBubble = true;
   }
}
box3.onclick = function(){
   alert('box3');
}

 

二、BOM

瀏覽器對象模型(browser object  model

2.1捲動事件

當視窗無論向上向下捲動的時候,比如鍵盤↓了,滾動滑鼠滾輪,拖拽滾動條,都會觸發這個事件。

window.onscroll=function(){

}

 

2.2視窗的寬度和高度

認識一個對象:

 document.documentElement

 

就是頁面document,想要得到視窗的寬度和高度,不是window對象,而是document對象,所以:

 document.documentElement.clientWidth

 document.documentElement.clientHeight

 

但是去掉頁面DTD,或IE678瀏覽器中,把下麵的語句當做瀏覽器視窗的寬度和高度

 document.body.clientWidth

 document.body.clientWidth

 

所以相容語法:

 document.documentElement.clientWidth || document.body.clientWidth;

 document.documentElement.clientHeight || document.body.clientWidth;


2.3視窗的捲動值

相容語法:

 document.documentElement.scrollTop || document.body.scrollTop

 

相容所有瀏覽器

 document.documentElement.scrollTop

 

相容不寫DTD的情況下:

 document.body.scrollTop

 


三、滑鼠位置

當我們給某一個盒子添加滑鼠事件監聽時(clickmouseovermouseentermouseout等事件),都一定會有以下四組值:

 event.pageX         event.pageY

 event.screenX       event.screenY

 event.clientX       event.clientY

 event.offsetX       event.offsetY

event.pageY    表示滑鼠指針,到頁面頂端的距離。IE678不相容

event.screenY  表示滑鼠指針,到屏幕頂端的距離

event.clientY  表示滑鼠指針,到視口頂端的距離(視口就是當前可視視窗)

event.offsetY  表示滑鼠指針,到盒子頂端的距離

規律:

1、當頁面沒有捲動的時候,pageY一定等價於clientY。或換句話說pageY等價於clientY+頁面捲動的值scrollTop

2IE678不相容pageXpageY

3offsetX/Y會被兒子影響。

 

 

offsetX/Y指的不是距離你監聽的那個盒子左上角的距離,而是指的你現在滑鼠指針所在位置到此時最內層盒子左上角的距離。

 


四、盒子位置

任何一個元素都有offsetParent屬性,和offsetLeftoffsetTop屬性

 


4.1計算盒子在頁面中的凈位置

現在我們就可以用offsetParentoffsetTop/Left計算一個元素的凈位置了,是一個迭代的過程。

xiaoming的凈位置:xiaoming.offsetTop + xiaoming.offsetParentxiaoming.offsetParent.borderTop ...

由於IE8很特殊,所以我們迫切的需要知道瀏覽器是不是IE8。所以使用:

window.navigator.userAgent

來檢測瀏覽器的版本。

 

 

 

 

 

 

 var ie8 = window.navigator.userAgent.indexOf("MSIE 8.0") != -1;

 

下麵的函數就是得到一個元素在頁面上的總凈位置:

function offset(o){
    //初始值
     var result = {
        "top" : o.offsetTop,
        "left" : o.offsetLeft
     }
     //判斷瀏覽器是不是IE8
     var isIE8 = window.navigator.userAgent.indexOf("MSIE 8.0") != -1;
     //迴圈迭代,尋找父親
     while(o = o.offsetParent){
        //計算後的邊框的值
        if(window.getComputedStyle){
          var borderTop = parseInt(getComputedStyle(o)['border-top-width']);
          var borderLeft = parseInt(getComputedStyle(o)['border-left-width']);
        }else{
          var borderTop = parseInt(o.currentStyle['borderTopWidth']);
          var borderLeft = parseInt(o.currentStyle['borderLeftWidth']);
        }

        //驗證一下,萬一borderTop是undefined或NaN,此時修正為0
        if(isNaN(borderTop)){
            borderTop = 0;
        }
        if(isNaN(borderLeft)){
            borderLeft = 0;
        }
        //如果瀏覽器版本不是IE8那麼就加上邊框,如果是IE8就不需要加邊框,拋出自己
        !isIE8 && (result.top += borderTop);
        !isIE8 && (result.left += borderLeft);
        result.top += o.offsetTop;
        result.left += o.offsetLeft;
     }
     return result;
 }

4.2曲線救國得到滑鼠在盒子中的位置

var box = document.getElementById("box");
var result = document.getElementById("result");
//監聽父親滑鼠移動的時候,滑鼠指針的offsetX值和offsetY值
box.onmousemove = function(event){
    var event = event || window.event;
    var x = event.pageX - getAllOffset(box).left;
    var y = event.pageY - getAllOffset(box).top;
    result.innerHTML = x + "," + y;
}

 

由於IE低版本不相容pageXpageY,所以用clientX/Y加上捲動值

var box = document.getElementById("box");
var result = document.getElementById("result");
//監聽父親滑鼠移動的時候,滑鼠指針的offsetX值和offsetY值
box.onmousemove = function(event){
    var event = event || window.event;
    //曲線救國!!!!得到視窗捲動的值
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
    //滑鼠的offsetX、offsetY等於視口的值,加上捲動值減去凈位置。
    var x = event.clientX + scrollTop - getAllOffset(box).left;
    var y = event.clientY + scrollLeft - getAllOffset(box).top;
    result.innerHTML = x + "," + y;
}

五、拖拽

5.1 在頁面上拖拽

頁面上的元素,能夠被滑鼠拖拽。整體思路:

① 當滑鼠在img上按下去的時候,註冊document的滑鼠移動事件監聽;反之,當滑鼠在屏幕任何位置抬起的時候,剝奪document的滑鼠移動事件監聽。

② 為了讓滑鼠能夠一直按住圖片的同一個位置,所以要在mousedown的一瞬間記錄誤差(見下圖)。

 

var img = document.getElementsByTagName('img')[0];
//滑鼠指針在圖片上按下的時候
img.onmousedown = function(event){
    var event = event || window.event;
    //記錄誤差,目的是當我按住baby的腦門子拖拽的時候,滑鼠指針一直在腦門子上。
    var dx = event.offsetX;
    var dy = event.offsetY;
    //註冊新的事件
    //在document上移動的時候,讓img跟隨滑鼠
    document.onmousemove = function(event){
        var event = event || window.event;
        //移動的時候top值等於當前的滑鼠指針位置減去開始的時候的誤差
        var x = event.clientX - dx;
        var y = event.clientY - dy;
 
        img.style.left = x + "px";
        img.style.top = y + "px";
        //這個return false可以解決IE8的內置事件
        return false;
    }
    //這個return false可以解決IE8的內置事件
    return false;
}
//滑鼠指針在任何位置抬起的時候,刪除document上的move監聽
document.onmouseup = function(){
    document.onmousemove = null;
}

5.2在容器中拖拽

圖片在父級容器中拖拽的時候,不僅僅是給圖片加了一個限制區域,圖片的topleft參考點是父盒子左上角,滑鼠指針的位置點就不一致。圖片的topleft起點是A,而滑鼠指針clinetXY參考點是B點。

大家參考點就不一樣了。

 

方法:只要把它們的坐標統一就可以了,所以我們需要得到滑鼠指針相對於盒子的坐標位置,此時需要使用曲線救國,因為offsetX/Y會被兒子影響。

 

var img = document.getElementsByTagName('img')[0];
var box = document.getElementById('box');
//得到盒子的凈位置
var boxoft = offset(box).top;
var boxofl = offset(box).left;
console.log(boxoft,boxofl)
//滑鼠指針在圖片上按下的時候
img.onmousedown = function(event){
   var event = event || window.event;
   //記錄誤差,目的是讓我按住baby的腦門拖拽的時候,滑鼠指針一直在腦門上
   var dx = event.offsetX;
   var dy = event.offsetY;
   //滑鼠按下,然後執行滑鼠移動時間,接著在document上移動,讓img跟著移動
   document.onmousemove = function(event){
       var event = event || window.event;
       //曲線救國!!!!得到視窗捲動的值
       var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
       var scrollLeft = document.documentElement.scrollLeft|| document.body.scrollLeft;
       //滑鼠的offsetX、offsetY等於視口的值,加上捲動值減去凈位置
       //移動的時候top值等價於滑鼠指針位置減去開始按下的誤差
       var X = event.clientX + scrollLeft - boxofl - dx;
       var Y = event.clientY + scrollTop- boxoft - dy;
       console.log(X,Y)
       //驗收
       if(X > 300){
           X = 300;
       }else if(X < 0){
           X = 0;
       }
       if(Y > 300){
           Y = 300;
       }else if(Y < 0){
           Y = 0;
       }
       img.style.left = X+'px';
       img.style.top  = Y+'px';
       //這個return false可以解決瀏覽器內置事件
       return false;
    }
}
//在滑鼠指針任何位置抬起的時候,移除document上的move事件監聽
document.onmouseup = function(){
   document.onmousemove = null;
}

5.3放大鏡效果

和剛剛的拖拽不一樣,滑鼠指針不需要按下了,所以邏輯變得簡單了。

放大鏡的放大原理:不是真的放大,只是當左邊小放大鏡移動的時候,右邊的大圖按比例移動,形成放大的感覺。

比例問題:

小圖盒子350寬高,放大鏡175寬高

大圖盒子400寬高,圖片800寬高

這裡暗含了兩個1:2,比例一定要相同,如果比例不相同,放大鏡放大感覺就不一樣了,無法看全。

 


六、滑鼠滾輪事件

頁面中經常有滑鼠滾輪事件,比如做一個內置有縱向滾動條的盒子

ChromeIE各個版本瀏覽器都支持onmousewheel事件,表示滑鼠滾輪滾動的時候觸發,火狐不支持這個事件,它支持的是自己的DOMMouseScroll事件,我們不需要進行能力檢測,因為所有的瀏覽器遇見別人添加監聽的方法都不報錯(靜默)。

 

var box = document.getElementById('box');
//除了火狐瀏覽器之外,都支持以下這種監聽滾輪事件
box.onmousewheel = mousewheel;
//火狐獨有的,必須用DOM2級添加監聽
box.addEventListener('DOMMouseScroll',mousewheel,true);
//事件處理函數
function mousewheel(){
   alert('滾動了!!!');
}

滑鼠滾輪事件的event對象有屬性wheelDelta,火狐是detail屬性,可以反映你的滾輪方向和力度

非火狐向上120(力度越大數字越大),火狐向上是-3

非火狐向下-120(力度越大數字越大),火狐向上是3

所以要進行相容性處理,把它們的值統一為:1-1

 

box.onmousewheel = mousewheel;
//火狐獨有的,必須用DOM2級添加監聽
box.addEventListener('DOMMouseScroll',mousewheel,true);
//事件處理函數
function mousewheel(event){
   //進行方向的能力檢測,由於火狐和大家不一樣,用if分開判斷
   if(event.wheelDelta){
       //非火狐
       // if(event.wheelDelta > 0){
       //     var direction = 1;
       // }else{
       //     var direction = -1;
       // }
       var direction =  event.wheelDelta > 0 ? 1 : -1;
   }else{
       //火狐
       // if(event.detail > 0){
       //     var direction = -1;
       // }else{
       //     var direction = 1;
       // }
       var direction =  event.detail > 0 ? -1 : 1;
   }
   console.log(direction)
}

 


 

上一篇文章DOM2級小測試的正確答案:EFGHIBCD

解釋:

1、DOM0級只能添加到冒泡階段

2、DOM0級事件同名的會覆蓋

3、true表示捕獲,false表示冒泡,先捕獲,後冒泡

4、DOM2級的不會覆蓋,先寫的先執行

5、DOM2級最內層的不區分冒泡和捕獲,誰先寫誰執行,無論是DOM0還是DOM2

 


 

ps:儘量讓它越來越規範,前期的文章都是本人的學習時的筆記整理,希望看完後可以指點一二,提提意見多多交流; 

 

筆記流程:html>css>javascript>jquery>html5/css3>移動端>ajax>面向對象>canvas>nodejs>es678>vue>react>小程式>面試問題

 

意見請留言,郵箱:[email protected]

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言- Andorid SDK下載 baidu雲 提取碼:19jm 這次我們就來研究一下官方的例子之一的liveWallPaper,也就是開發Android的動態壁紙 先來看看這個例子運行的結果: 還是蠻可愛的嘛,那麼開始吧! 項目的目錄- framework中是live2d要用的必須的類 libs ...
  • 網上找了一個腳本,在其中進行了修改,只需要一條命令就可以了 支持自動導入配置文件 支持自動安裝p12證書 支持自動修改版本號和build版本號 支持自動修改app顯示名稱 支持自動修改bundle identifier 支持自動生成ipa文件到指定目錄 圖標和閃圖更換隻是一個簡單的拷貝工作,目前的腳 ...
  • Android 開發高手課 課後練習(1) 一、Chapter01 崩潰 https://time.geekbang.org/column/article/70602 https://github.com/AndroidAdvanceWithGeektime/Chapter01 1、遇到native ...
  • 程式36:有n個人圍成一圈,順序排號。從第一個人開始報數(從1到3報數),凡報到3的人推出圈子,問最後留下的是原來第幾號的那位 var n=20; var arr=[]; for(var i=0;i<n;i++){ arr.push(1); } for(var j=1,least=n;;j++){ ...
  • 這段時間學習了 socket.io ,用它寫了小項目,在此總結下它的基本使用方式和一些要點。 socket.io 是基於 Node.js 和 WebSocket 協議的實時通信開源框架,它包括客戶端的JavaScript和伺服器端的Node.js。 服務端 這裡後端使用的框架是 koa2 , soc ...
  • fetch("/") .then(response => response.json()) .then(json => { this.restaurants = json; console.log(this.restaurants.length) }) ...
  • 簡介 "Koa" 就是一種簡單好用的 Web 框架。它的特點是優雅、簡潔、表達力強、自由度高。本身代碼只有1000多行,所有功能都通過插件實現。 學前準備 檢查Nodejs版本 打開cmd命令行視窗 註意:Koa 必須使用 7.6 以上的版本。如果你的版本低於這個要求,就要先升級 Node。 "配套 ...
  • 還是先從一個題目開始: 寫一個隔1s輸出數組的一項的函數。 如果可以用ES6語法,則可以這麼寫: 但是如果把這裡的 改成 ,則輸出就會變成一連串的 。 有同學很快想到了這是閉包啊,因為 把函數加入到 中,所以等到setTimeout的函數體執行時, 已經走完了 迴圈,變成了 。`arr[arr.le ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...