麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > JavaScript > 正文

JS奇技之利用scroll來(lái)監(jiān)聽(tīng)resize詳解

2019-11-19 16:19:57
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

大家都知道知道原生的 resize 事件只能作用于 defaultView 即 window 上,那么我們應(yīng)該通過(guò)什么樣的方式來(lái)監(jiān)聽(tīng)其他元素的大小改變呢?筆者最近學(xué)習(xí)發(fā)現(xiàn)了一種神奇的方法,通過(guò) scroll 事件來(lái)間接實(shí)現(xiàn) resize 事件的監(jiān)聽(tīng),本文將對(duì)這種方式進(jìn)行原理的剖析與代碼實(shí)現(xiàn)。

原理

首先,我們先來(lái)看一下 scroll 事件是干嘛的。

The scroll event is fired when the document view or an element has been scrolled.

當(dāng)文檔視圖或者元素滾動(dòng)的時(shí)候會(huì)觸發(fā) scroll 事件。

也就是說(shuō)元素滾動(dòng)的時(shí)候會(huì)觸發(fā)這個(gè)事件,那么什么時(shí)候元素會(huì)滾動(dòng)?當(dāng)元素大于其父級(jí)元素,且父級(jí)元素允許其滾動(dòng)的時(shí)候,該元素可以進(jìn)行滾動(dòng)。換句話說(shuō),元素可以滾動(dòng)意味著父子元素大小不一致,這是這個(gè)方法的核心。

那么我們需要讓元素大小發(fā)生改變時(shí),使得 scrollLeft 或者 scrollTop 發(fā)生改變,從而觸發(fā) scroll 事件,進(jìn)一步得知其大小發(fā)生了改變。

監(jiān)聽(tīng)元素變大

元素變大的時(shí)候,我們可以看到更多,其內(nèi)部可滾動(dòng)區(qū)域?qū)⒙郎p小,但這并不會(huì)造成滾動(dòng)條位置的改變,但當(dāng)元素大到讓滾動(dòng)條消失的時(shí)候會(huì)讓 scrollLeft 或者 scrollTop 變成 0,這樣我們就知道了元素變大了,因此我們其實(shí)只需要 1px 來(lái)判斷,其圖示如下:

監(jiān)聽(tīng)元素變小

當(dāng)元素變小的時(shí)候,可滾動(dòng)區(qū)域會(huì)變大,滾動(dòng)條的位置其實(shí)并不會(huì)進(jìn)行改變,這里采取的做法是,讓可滾動(dòng)區(qū)域和父元素成一定的比例一起縮小,讓父元素來(lái)擠壓滾動(dòng)區(qū)域,從而間接改變滾動(dòng)條 scrollLeft 或者 scrollTop 的大小,文字描述可能不是很清楚,我們看下圖:

通過(guò)以上兩種方式,我們可以就可以獲得 resize 事件。

實(shí)現(xiàn)

首先,為了不影響原有的元素,我們應(yīng)當(dāng)創(chuàng)建一個(gè)和要監(jiān)聽(tīng)元素等大的元素,并對(duì)其進(jìn)行相關(guān)操作,然后我們需要兩個(gè)子元素來(lái)分別監(jiān)聽(tīng)元素變大和元素變小兩個(gè)情況。因此構(gòu)造如下的 HTML 結(jié)構(gòu):

<div class="resize-triggers"> <div class="expand-trigger"> <div></div> </div> <div class="contract-trigger"></div></div>

他們對(duì)應(yīng)的 CSS 如下:

.resize-triggers { visibility: hidden; opacity: 0;}.resize-triggers,.resize-triggers > div,.contract-trigger:before { content: " "; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;}.resize-triggers > div { overflow: auto;}.contract-triggers:before { width: 200%; height: 200%;}

其中 .expand-triggers 的子元素寬高應(yīng)當(dāng)保持大于父元素 1px,且兩個(gè)觸發(fā)器都應(yīng)當(dāng)保持在最右下角的狀態(tài),因此我們可以實(shí)現(xiàn)如下的狀態(tài)重置函數(shù),并在初始化和每次滾動(dòng)事件的時(shí)候調(diào)用:

/** * 重置觸發(fā)器 * @param element 要處理的元素 */const resetTrigger = function(element) { const trigger = element.__resizeTrigger__; // 要重置的觸發(fā)器 const expand = trigger.firstElementChild; // 第一個(gè)子元素,用來(lái)監(jiān)聽(tīng)變大 const contract = trigger.lastElementChild; // 最后一個(gè)子元素,用來(lái)監(jiān)聽(tīng)變小 const expandChild = expand.firstElementChild; // 第一個(gè)子元素的第一個(gè)子元素,用來(lái)監(jiān)聽(tīng)變大 contract.scrollLeft = contract.scrollWidth; // 滾動(dòng)到最右 contract.scrollTop = contract.scrollHeight; // 滾動(dòng)到最下 expandChild.style.width = expand.offsetWidth + 1 + 'px'; // 保持寬度多1px expandChild.style.height = expand.offsetHeight + 1 + 'px'; // 保持高度多1px expand.scrollLeft = expand.scrollWidth; // 滾動(dòng)到最右 expand.scrollTop = expand.scrollHeight; // 滾動(dòng)到最右};

我們可以用如下函數(shù)檢測(cè)元素大小是否發(fā)生了改變:

/** * 檢測(cè)觸發(fā)器狀態(tài) * @param element 要檢查的元素 * @returns {boolean} 是否改變了大小 */const checkTriggers = function(element) { // 寬度或高度不一致就返回true return element.offsetWidth !== element.__resizeLast__.width || element.offsetHeight !== element.__resizeLast__.height;};

最終,我們可以實(shí)現(xiàn)簡(jiǎn)單的事件監(jiān)聽(tīng)的添加:

/** * 添加大小更改監(jiān)聽(tīng) * @param element 要監(jiān)聽(tīng)的元素 * @param fn 回調(diào)函數(shù) */export const addResizeListener = function(element, fn) {if (isServer) return; // 服務(wù)器端直接返回 if (attachEvent) { // 處理低版本ie element.attachEvent('onresize', fn); } else {if (!element.__resizeTrigger__) { // 如果沒(méi)有觸發(fā)器  if (getComputedStyle(element).position === 'static') {  element.style.position = 'relative'; // 將static改為relative  }createStyles();  element.__resizeLast__ = {}; // 初始化觸發(fā)器最后的狀態(tài)  element.__resizeListeners__ = []; // 初始化觸發(fā)器的監(jiān)聽(tīng)器  const resizeTrigger = element.__resizeTrigger__ = document.createElement('div'); // 創(chuàng)建觸發(fā)器  resizeTrigger.className = 'resize-triggers';  resizeTrigger.innerHTML = '<div class="expand-trigger"><div></div></div><div class="contract-trigger"></div>';  element.appendChild(resizeTrigger); // 添加觸發(fā)器  resetTrigger(element); // 重置觸發(fā)器  element.addEventListener('scroll', scrollListener, true); // 監(jiān)聽(tīng)滾動(dòng)事件  /* Listen for a css animation to detect element display/re-attach */  // 監(jiān)聽(tīng)CSS動(dòng)畫(huà)來(lái)檢測(cè)元素顯示或者重新添加  if (animationStartEvent) { // 動(dòng)畫(huà)開(kāi)始  resizeTrigger.addEventListener(animationStartEvent, function(event) { // 增加動(dòng)畫(huà)開(kāi)始的事件監(jiān)聽(tīng)   if (event.animationName === RESIZE_ANIMATION_NAME) { // 如果是大小改變事件   resetTrigger(element); // 重置觸發(fā)器   }  });  } } element.__resizeListeners__.push(fn); // 加入該回調(diào) }};

以及如下的函數(shù)來(lái)移除事件監(jiān)聽(tīng):

/** * 移除大小改變的監(jiān)聽(tīng) * @param element 被監(jiān)聽(tīng)的元素 * @param fn 對(duì)應(yīng)的回調(diào)函數(shù) */export const removeResizeListener = function(element, fn) {if (attachEvent) { // 處理ie element.detachEvent('onresize', fn); } else { element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); // 移除對(duì)應(yīng)的回調(diào)函數(shù) if (!element.__resizeListeners__.length) { // 如果全部時(shí)間被移除  element.removeEventListener('scroll', scrollListener); // 移除滾動(dòng)監(jiān)聽(tīng)  element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__); // 移除對(duì)應(yīng)的觸發(fā)器,但保存下來(lái) } }};

其他

其中有部分內(nèi)容是用來(lái)優(yōu)化的,并不影響基礎(chǔ)功能,如對(duì)服務(wù)器渲染、客戶(hù)端渲染的區(qū)分,對(duì) IE 的特殊處理,以及通過(guò) opacity 的動(dòng)畫(huà)來(lái)解決 chrome 上的bug。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如有疑問(wèn)大家可以留言交流,謝謝大家對(duì)武林網(wǎng)的支持。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 看全色黄大色黄大片女图片 | 免费黄色大片网站 | 久久美女免费视频 | av色偷偷| 最新一区二区三区 | 天天鲁在线视频免费观看 | 男人久久天堂 | 久久精品视频69 | 日韩1区 | 欧美成人做爰高潮片免费视频 | 中文在线观看免费视频 | 亚洲精品一区中文字幕 | 中文黄色一级片 | 久久艹精品视频 | 一级毛片在线免费播放 | 在线成人免费观看www | 黄色免费影片 | 久久精品亚洲成在人线av网址 | 中国大陆一级毛片 | 国产亚洲欧美一区久久久在 | 天天看天天摸天天操 | 亚洲综合网站 | 国产在线精品91 | lutube成人福利在线观看污 | 色七七久久影院 | 久草热久草视频 | 亚洲午夜影院在线观看 | 久久国产综合视频 | 中文字幕偷拍 | 国产一级爱c视频 | 香蕉视频18 | 成年人视频免费 | 国产精品久久久久久238 | a视频在线免费观看 | 欧美a在线观看 | 狼伊千合综网中文 | 国产毛片毛片 | 成年免费观看视频 | 91麻豆精品国产91久久久更新资源速度超快 | 国产一区视频观看 | 国产精品视频二区不卡 |