[前端學(xué)習(xí)]js特效部分學(xué)習(xí)筆記,第二天

事件對(duì)象

  • 在我們注冊(cè)事件后,并不會(huì)直接調(diào)用這個(gè)匿名函數(shù),而是觸發(fā)這個(gè)事件時(shí)才執(zhí)行內(nèi)部代碼。
  • 所以真正調(diào)用匿名函數(shù)的是瀏覽器。瀏覽器在調(diào)用時(shí)會(huì)傳入一個(gè)對(duì)象參數(shù)(event),哪怕我們沒寫形參,也是會(huì)傳入的。這個(gè)就叫作事件對(duì)象。
  • 事件對(duì)象內(nèi)部存儲(chǔ)的是一系列與該事件有關(guān)系的屬性值。所以如果想獲取事件對(duì)象,在給匿名函數(shù)寫一個(gè)形參就可以。

獲取事件對(duì)象兼容寫法

  • 之前已經(jīng)說過了,通過形參可以直接獲取到事件對(duì)象,但是這種方法主流瀏覽器支持,ie678不支持,所以一般推薦使用兼容的方法。
    document.onclick = function (event) {
    var event = event || window.event;
    };
  • 上面是隨便注冊(cè)了一個(gè)事件作為例子,設(shè)置一個(gè)形參,并在函數(shù)內(nèi)部聲明一個(gè)event變量來存放事件對(duì)象。
  • 寫或的原因是使用到了它的短路判斷,如果第一個(gè)值為true,說明瀏覽器支持這種方法,根據(jù)或的短路原理,第一個(gè)為true直接返回該值。如果第一個(gè)不為true才繼續(xù)往下判斷。

三個(gè)重要坐標(biāo)

  • 事件對(duì)象.screenX & 事件對(duì)象.screenY 獲取鼠標(biāo)在屏幕中的坐標(biāo)
  • 事件對(duì)象.clientX & 事件對(duì)象.clientY 獲取鼠標(biāo)在窗口中的坐標(biāo)
  • 事件對(duì)象.pageX & 事件對(duì)象.pageY 獲取鼠標(biāo)在頁面中的坐標(biāo)
  • clientXY和pageXY的區(qū)別在于:如果頁面很長,那么pageXY會(huì)以整個(gè)頁面來計(jì)算坐標(biāo),而clientXY則是只會(huì)根據(jù)當(dāng)前的顯示窗口來計(jì)算坐標(biāo)。

鼠標(biāo)在頁面中坐標(biāo)的兼容寫法

  • 也是ie678不支持pageX和pageY,但是ie678卻支持clientXY,所以建議使用以下兼容寫法:
    pageX = event.pageX || event.clientX + document.documentElement.scrollLeft //Y軸同理
  • 獲取鼠標(biāo)在窗口中的位置,再加上被卷去的部分,也可以得到鼠標(biāo)在頁面中的坐標(biāo)

鼠標(biāo)跟隨案例總結(jié)

  • 比較簡單的一個(gè)案例,主要就是獲取事件對(duì)象中的pageX和pageY值,并賦給添加了定位元素的left和top,就能實(shí)現(xiàn)鼠標(biāo)跟隨效果
  • 有一個(gè)稍微要注意的是,如果直接賦值那么元素在跟隨的時(shí)候,是左上角對(duì)齊鼠標(biāo)坐標(biāo)。如果想要讓元素中心對(duì)齊鼠標(biāo)坐標(biāo),要減去元素自身高和寬分別的一半。

獲取鼠標(biāo)在盒子中的坐標(biāo)

  • 首先要知道,鼠標(biāo)在盒子中的坐標(biāo)是不能直接獲取的,需要通過計(jì)算。
  • 計(jì)算的原理,用鼠標(biāo)在頁面中的坐標(biāo)值,減去盒子本身到body兩側(cè)的距離,那么剩下的就是鼠標(biāo)在盒子中的坐標(biāo)值
  • 下面例子做一個(gè)參考:
    boxX = pageX - box.offsetLeft;
    boxY = pageY - box.offsetTop;
  • 同時(shí)本節(jié)又講到了一個(gè)新的事件,onmousemove鼠標(biāo)移動(dòng)事件

放大鏡案例總結(jié)

  • 這個(gè)案例實(shí)際上運(yùn)用到了,上面講的幾個(gè)知識(shí)點(diǎn),包括獲取鼠標(biāo)在盒子內(nèi)坐標(biāo),設(shè)置鼠標(biāo)跟隨盒子。
  • 有兩個(gè)重點(diǎn):
    • 一是在盒子內(nèi)部設(shè)置鼠標(biāo)跟隨盒子時(shí),要限制跟隨盒子可以移動(dòng)的范圍,不能讓其超出盒子
    • 二是讓大圖同步移動(dòng)時(shí),比例的計(jì)算問題。當(dāng)然比例不是一定要計(jì)算,直接給一個(gè)對(duì)應(yīng)的比值也行,不過為了精確顯示,建議還是要計(jì)算出來。公式就是:大圖應(yīng)該設(shè)置坐標(biāo) = rate(比例) * 跟隨圖坐標(biāo)。rate的公式為:rate = 大圖可以移動(dòng)總距離 / 跟隨圖可以移動(dòng)總距離
  • 詳細(xì)代碼參考案例,更容易理解

鼠標(biāo)拖拽案例總結(jié)

  • 這個(gè)案例的重點(diǎn)在于:當(dāng)鼠標(biāo)移動(dòng)時(shí),如果不計(jì)算那么默認(rèn)盒子左上角跟隨鼠標(biāo)移動(dòng),這明顯不是我們想要的效果。
  • 所以需要計(jì)算盒子應(yīng)該移動(dòng)的距離,首先要計(jì)算鼠標(biāo)在按下時(shí),在盒子的內(nèi)的坐標(biāo),然后再用鼠標(biāo)在頁面中的坐標(biāo)減去盒子的坐標(biāo),就可以讓鼠標(biāo)按下的那個(gè)點(diǎn)一直對(duì)準(zhǔn)鼠標(biāo)進(jìn)行跟隨。
  • 實(shí)際上就是在移動(dòng)時(shí),默認(rèn)先讓盒子移動(dòng)了鼠標(biāo)在盒子中坐標(biāo)的距離,然后再跟隨鼠標(biāo)移動(dòng),這樣看起來就不是左上角跟隨了。
  • 并且涉及到了清除選中文字狀態(tài)的代碼:
    window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

滾動(dòng)條案例總結(jié)

  • 滾動(dòng)條案例邏輯其實(shí)是結(jié)合了上面的兩個(gè)案例,有以下幾個(gè)重點(diǎn)
  • 滾動(dòng)條的長度不是定值,需要通過公式來計(jì)算:滾動(dòng)條高度/側(cè)邊欄高度 = 內(nèi)容顯示高度/內(nèi)容總高度
  • 想要鼠標(biāo)拖動(dòng)時(shí)不是滾動(dòng)條頂部對(duì)齊跟隨移動(dòng),就要求到鼠標(biāo)在滾動(dòng)條內(nèi)的坐標(biāo),用鼠標(biāo)在頁面中的坐標(biāo)-盒子到頂部的距離-滾動(dòng)條到盒子頂部的距離,就可以得到。然后用鼠標(biāo)在盒子中的坐標(biāo)-鼠標(biāo)在滾動(dòng)條中的坐標(biāo),讓滾動(dòng)條移動(dòng)時(shí)默認(rèn)先往上走這個(gè)距離,就可以實(shí)現(xiàn)滾動(dòng)條根據(jù)鼠標(biāo)點(diǎn)擊的那個(gè)點(diǎn)來跟隨移動(dòng)
  • 要讓內(nèi)容根據(jù)滾動(dòng)條移動(dòng)的比例來移動(dòng),就要根據(jù)這個(gè)公式:內(nèi)容應(yīng)該移動(dòng)的位置/滾動(dòng)條當(dāng)前的位置 = 內(nèi)容能夠移動(dòng)的總距離/滾動(dòng)條能夠移動(dòng)的總距離

瀑布流案例總結(jié)

  • 瀑布流案例的幾個(gè)重點(diǎn):
  • 求出每行剩余空白寬度后,還要除以列數(shù)-1,平均分配空白間距
  • 第一行布局不需要設(shè)置top值
  • left設(shè)置時(shí),值 = (圖片寬度 + 間距) * (對(duì)應(yīng)索引||最小高度列索引值),這樣才能讓圖片的位置在其對(duì)應(yīng)列或者最小高度列上
  • 第二行開始要把圖片放到高度最小的那列上,所以需要一個(gè)數(shù)組來存放每列的高度,然后比較數(shù)組中的值,找出高度最小的那列。
  • 每次把圖片放到高度最小那列后,還要給那列的高度值重新賦值,值 = 原高度+新圖片高度+間距
  • 瀑布流需要瀏覽器滾動(dòng)事件window.onscroll,為了避免出現(xiàn)滾動(dòng)時(shí)出現(xiàn)空白影響效果,所以在追加圖片時(shí),判斷條件為:窗口可視區(qū)高度 + 頁面被卷去高度 > 最小高度列的高度值,一旦大于肯定會(huì)出現(xiàn)空白,所以就要追加圖片,并再次調(diào)用瀑布流布局函數(shù)

事件冒泡

  • 在一個(gè)對(duì)象上觸發(fā)某類事件(比如單擊onclick事件),如果此對(duì)象定義了此事件的處理程序,那么此事件就會(huì)調(diào)用這個(gè)處理程序,如果沒有定義此事件處理程序或者事件返回true,那么這個(gè)事件會(huì)向這個(gè)對(duì)象的父級(jí)對(duì)象傳播,從里到外,直至它被處理(父級(jí)對(duì)象所有同類事件都將被激活),或者它到達(dá)了對(duì)象層次的最頂層,即document對(duì)象(有些瀏覽器是window)。正常情況下這個(gè)不會(huì)有什么影響
  • 但是也有特例,比如鼠標(biāo)離開事件,如果父元素注冊(cè)了鼠標(biāo)事件,子元素沒有注冊(cè)。當(dāng)鼠標(biāo)離開子元素時(shí),雖然沒有注冊(cè)事件不會(huì)執(zhí)行,但是該事件確實(shí)觸發(fā)了就會(huì)冒泡,到上級(jí)發(fā)現(xiàn)父元素注冊(cè)了。就會(huì)執(zhí)行父元素注冊(cè)的鼠標(biāo)離開事件,這顯然是不行的

阻止事件冒泡

  • 為了避免事件冒泡而產(chǎn)生的一些不可控結(jié)果,我們需要阻止事件冒泡,要阻止誰的事件冒泡,就在讓該元素調(diào)用阻止冒泡的方法。
    event.stopPropagation();
  • 調(diào)用這個(gè)方法,需要先獲取事件對(duì)象來配合

阻止事件冒泡兼容寫法

  • 寫法如下
    if( event.stopPropagation ) {
    event.stopPropagation();
    } else {
    event.cancelBubble = true;
    }
  • 如果調(diào)用stopPropagation方法有返回值,說明瀏覽器支持,如果為空說明瀏覽器不支持,那就設(shè)置cancelBubble屬性。一般只有ie678不支持stopPropagation方法

獲取事件目標(biāo)

  • var target = event.target || event.srcElement 可以獲取事件的源目標(biāo),就是說由哪個(gè)元素觸發(fā)了這個(gè)事件,就獲取到哪個(gè)元素,target.id還能獲取該元素的id值

事件監(jiān)聽器

  • 如果使用之前的事件注冊(cè)方法,那么同一個(gè)元素相同的事件會(huì)相互覆蓋,一般只會(huì)保留后寫注冊(cè)的事件
  • 但是如果使用事件監(jiān)聽器的方法來注冊(cè)事件,那么即使是同一元素的相同事件也不會(huì)覆蓋,而是根據(jù)注冊(cè)順序依次執(zhí)行
  • 主流瀏覽器的寫法:
    元素.addEventListener([事件名字符串,注意這里事件名不加on],[事件處理程序function],[是否捕獲true||false]);
  • ie678的寫法:
    元素.attachEvent([事件名字符串,注意這里事件名要加on],[事件處理程序function]);
  • 捕獲參數(shù)詳解:如果傳入的參數(shù)是false,就是不使用捕獲,那么事件的執(zhí)行順序就是默認(rèn)順序冒泡,從內(nèi)到外;如果傳入true使用捕獲,那么瀏覽器會(huì)從外到內(nèi)先捕獲事件源,找到事件源后,再執(zhí)行冒泡。捕獲就是從外內(nèi)到尋找的過程。

監(jiān)聽器移除事件方法

  • 普通注冊(cè)事件的方式,想要移除事件,利用事件會(huì)相互覆蓋的原理,重新注冊(cè)該事件并賦值為空,就能移除。但是如果是使用監(jiān)聽器來注冊(cè)的事件,那么需要用到以下方法:
  • 主流瀏覽器:
    元素.removeEventListener()[事件名字符串,注意這里事件名不加on],[處理函數(shù)名],[是否捕獲true||false]);
  • ie678
    元素.detachEvent([事件名字符串,注意這里事件名要加on],[處理函數(shù)名]);
  • 從代碼可以看出,如果要移除事件,需要傳入事件處理函數(shù)的名稱,所以如果使用監(jiān)聽器注冊(cè)函數(shù),并且在之后想要移除,那么建議不要用匿名函數(shù),直接在外部寫好傳入函數(shù)名稱來注冊(cè),也方便后面移除

事件階段

  • 事件階段也叫做事件流模型。通過event.phase可以查看事件的各個(gè)階段
  • 一個(gè)完整的事件三階段:從外到內(nèi)捕獲階段-事件目標(biāo)執(zhí)行階段-事件冒泡階段
  • 但是傳統(tǒng)注冊(cè)事件方法,和監(jiān)聽器注冊(cè)事件方法傳入false參數(shù),它都是跳過了捕獲階段,直接找到事件源執(zhí)行再事件冒泡,目前捕獲階段我們很少接觸到
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • offset家族三大家族和一個(gè)事件對(duì)象三大家族(offset/scroll/client)事件對(duì)象/event ...
    Yuann閱讀 1,087評(píng)論 0 5
  • 事件流 IE和Netscape開發(fā)團(tuán)隊(duì)提出了完全相反的兩種事件流的概念,事件冒泡流和事件捕獲流。 事件冒泡 事件由...
    exialym閱讀 1,055評(píng)論 0 9
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進(jìn)階之旅閱讀 115,557評(píng)論 24 450
  • (續(xù)jQuery基礎(chǔ)(1)) 第5章 DOM節(jié)點(diǎn)的復(fù)制與替換 (1)DOM拷貝clone() 克隆節(jié)點(diǎn)是DOM的常...
    凜0_0閱讀 1,513評(píng)論 0 8
  • 藝術(shù)是心靈之事,所以任何一項(xiàng)科學(xué)性的藝術(shù)研究必然屬于心理學(xué)范疇。它可能涉及其他領(lǐng)域,但是,屬于心理學(xué)范疇則永...
    Jelly菌閱讀 10,765評(píng)論 1 7

友情鏈接更多精彩內(nèi)容