JS如何監(jiān)聽div的resize事件詳解
需求
開發(fā)過(guò)程中經(jīng)常遇到的一個(gè)問(wèn)題就是如何監(jiān)聽一個(gè)div的size變化。
比如我用canvas繪制了一個(gè)chart,當(dāng)canvas的size發(fā)生變化的時(shí)候,需要重新繪制里面的內(nèi)容,這個(gè)時(shí)候就需要監(jiān)聽resize事件做處理。
window上雖然可以添加resize事件監(jiān)聽,但這并不能滿足我們的需求,因?yàn)楹芏鄷r(shí)候,div的size發(fā)生了變化,但是window的size并沒(méi)有改變。
不過(guò)我們可以間接利用window的resize事件監(jiān)聽來(lái)實(shí)現(xiàn)對(duì)于某個(gè)div的resize事件監(jiān)聽,請(qǐng)看下面具體實(shí)現(xiàn)。
對(duì)于div的resize事件的監(jiān)聽,實(shí)現(xiàn)方式有很多,比如周期性檢查,通過(guò)scroll事件等等,本文主要介紹通過(guò)object元素來(lái)實(shí)現(xiàn)監(jiān)聽。
具體實(shí)現(xiàn)
/** * Created by taozh on 2017/5/6. * taozh1982@gmail.com */ var EleResize = { _handleResize: function (e) { var ele = e.target || e.srcElement; var trigger = ele.__resizeTrigger__; if (trigger) { var handlers = trigger.__z_resizeListeners; if (handlers) { var size = handlers.length; for (var i = 0; i < size; i++) { var h = handlers[i]; var handler = h.handler; var context = h.context; handler.apply(context, [e]); } } } }, _removeHandler: function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { var size = handlers.length; for (var i = 0; i < size; i++) { var h = handlers[i]; if (h.handler === handler && h.context === context) { handlers.splice(i, 1); return; } } } }, _createResizeTrigger: function (ele) { var obj = document.createElement('object'); obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;'); obj.onload = EleResize._handleObjectLoad; obj.type = 'text/html'; ele.appendChild(obj); obj.data = 'about:blank'; return obj; }, _handleObjectLoad: function (evt) { this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__; this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize); } }; if (document.attachEvent) {//ie9-10 EleResize.on = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (!handlers) { handlers = []; ele.__z_resizeListeners = handlers; ele.__resizeTrigger__ = ele; ele.attachEvent('onresize', EleResize._handleResize); } handlers.push({ handler: handler, context: context }); }; EleResize.off = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { EleResize._removeHandler(ele, handler, context); if (handlers.length === 0) { ele.detachEvent('onresize', EleResize._handleResize); delete ele.__z_resizeListeners; } } } } else { EleResize.on = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (!handlers) { handlers = []; ele.__z_resizeListeners = handlers; if (getComputedStyle(ele, null).position === 'static') { ele.style.position = 'relative'; } var obj = EleResize._createResizeTrigger(ele); ele.__resizeTrigger__ = obj; obj.__resizeElement__ = ele; } handlers.push({ handler: handler, context: context }); }; EleResize.off = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { EleResize._removeHandler(ele, handler, context); if (handlers.length === 0) { var trigger = ele.__resizeTrigger__; if (trigger) { trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize); ele.removeChild(trigger); delete ele.__resizeTrigger__; } delete ele.__z_resizeListeners; } } } }
測(cè)試代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Resize</title> <script src="./EleResize.js"></script> <style> html, body { margin: 0; padding: 0; width: 100%; height: 100%; } #resizeDiv { width: 60%; height: 60%; border: 1px solid red; margin: 20px; } button { margin: 20px 20px 0; } </style> </head> <body> <button onclick="addListener()">addListener</button> <button onclick="removeListener()">removeListener</button> <button onclick="resize()">resize</button> <div id="resizeDiv"></div> <script> var resizeDiv = document.getElementById('resizeDiv'); function resize() { resizeDiv.style.width = "200px"; } var listener = function () { console.log("resize"); }; function addListener() { EleResize.on(resizeDiv, listener); } function removeListener() { EleResize.off(resizeDiv, listener) } </script> </body> </html>
原理
這里的具體實(shí)現(xiàn)分兩類,
- ie9-10
默認(rèn)支持div的resize事件,可以直接通過(guò)div.attachEvent('onresize', handler);的方式實(shí)現(xiàn)
- 其它瀏覽器
通過(guò)在div中添加一個(gè)內(nèi)置object元素實(shí)現(xiàn)監(jiān)聽。
設(shè)置object元素的style使其填充滿div,這樣當(dāng)div的size發(fā)生變化時(shí),object的size也會(huì)發(fā)生變化。
然后監(jiān)聽object元素的contentDocument.defaultView(window對(duì)象)的resize事件。
注:本文提供的是如何監(jiān)聽resize事件,其實(shí)在resize時(shí),可能會(huì)連續(xù)快速的觸發(fā)(比如拖動(dòng)瀏覽器),為了提高效率,可以考慮使用批處理的模式。
到此這篇關(guān)于JS如何監(jiān)聽div的resize事件的文章就介紹到這了,更多相關(guān)JS監(jiān)聽div的resize事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js實(shí)現(xiàn)屏幕自適應(yīng)局部代碼分享
這篇文章主要介紹了js實(shí)現(xiàn)屏幕自適應(yīng)局部代碼分享,需要的朋友可以參考下2015-01-01js判斷手機(jī)是否安裝并打開app,未安裝則安裝app【兼容Android、ios,親測(cè)可用】
這篇文章主要介紹了js判斷手機(jī)是否安裝并打開app,未安裝則安裝app,通過(guò)調(diào)用瀏覽器判斷app,兼容Android、ios等系統(tǒng),,需要的朋友可以參考下2023-05-05

JS中定時(shí)器的使用及頁(yè)面切換時(shí)定時(shí)器無(wú)法清除問(wèn)題的解決辦法

JS解決IOS中拍照?qǐng)D片預(yù)覽旋轉(zhuǎn)90度BUG的問(wèn)題

js中點(diǎn)擊空白區(qū)域時(shí)文本框與隱藏層的顯示與影藏問(wèn)題