この記事では、JS でスクロールを使用してサイズ変更を監視することに関する関連情報を、サンプル コードを通じて詳細に紹介します。この記事は、学習や仕事に役立つ特定の価値があります。以下を見てみましょう。
前書き
ネイティブのサイズ変更イベントがdefaultView、つまりウィンドウでのみ動作できることは誰もが知っていますが、他の要素のサイズ変更をどのように監視すればよいでしょうか?著者は最近、スクロール イベントを通じてサイズ変更イベントの監視を間接的に実装する魔法の方法を発見しました。この記事では、この方法の原理とコード実装を分析します。
原理
まず、スクロールイベントが何をするのかを見てみましょう。
Scroll イベントは、ドキュメント ビューまたは要素がスクロールされたときに発生します。
Scroll イベントは、ドキュメント ビューまたは要素がスクロールされたときに発生します。
つまり、このイベントは要素がスクロールするとトリガーされます。では、要素はいつスクロールするのでしょうか?要素が親要素より大きく、親要素がスクロールを許可する場合、要素はスクロールできます。つまり、スクロールできる要素は、親要素と子要素のサイズが同じではないことを意味し、これがこのアプローチの核心です。
次に、要素のサイズが変更されたときにscrollLeftまたはscrollTopを変更する必要があります。これにより、scrollイベントがトリガーされ、サイズが変更されたことをさらに知ることができます。
要素が大きくなるのを聞いてください
要素が大きくなると、より多くのものが表示され、その内部のスクロール可能な領域は徐々に減少しますが、これによってスクロールバーの位置は変更されません。要素が大きくなると、スクロールバーが消えるほど多くのものが見えるようになります。要素が大きくなりすぎると、scrollLeft またはscrollTop が 0 に変化するため、要素が大きくなったことがわかります。したがって、実際には 1px だけで判断できます。アイコンは次のとおりです。
要素が小さくなるのを聞いています
要素が小さくなると、スクロール可能な領域は大きくなりますが、スクロールバーの位置は実際には変わりません。ここで採用されているアプローチは、スクロール可能領域と親要素を一定の比率にすることです。一緒に縮小し、親要素がスクロール領域を圧迫することで、間接的にスクロール バーのサイズを変更します。下の図を見てみましょう:
上記の 2 つのメソッドを通じて、サイズ変更イベントを取得できます。
実装
まず、元の要素に影響を与えないように、監視する要素と同じ大きさの要素を作成し、その要素に対して関連する操作を実行する必要があります。要素の変化をそれぞれ監視します。要素が大きくなる場合と小さくなる場合の 2 つの状況があります。したがって、次の HTML 構造が構築されます:
<p class="resize-triggers"> <p class="expand-trigger"> <p></p> </p> <p class="contract-trigger"></p> </p>
対応する CSS は次のとおりです:
.resize-triggers { visibility: hidden; opacity: 0; } .resize-triggers, .resize-triggers > p, .contract-trigger:before { content: " "; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > p { overflow: auto; } .contract-triggers:before { width: 200%; height: 200%; }
の子要素の幅と高さは親要素より 1 ピクセル大きいままにする必要があり、その 2 つの要素は .expand-triggers
triggers は右下隅の状態内に留まる必要があるため、次の状態リセット関数を実装し、初期化中および各スクロール イベント中にそれを呼び出すことができます:
/** * 重置触发器 * @param element 要处理的元素 */ const resetTrigger = function(element) { const trigger = element.resizeTrigger; // 要重置的触发器 const expand = trigger.firstElementChild; // 第一个子元素,用来监听变大 const contract = trigger.lastElementChild; // 最后一个子元素,用来监听变小 const expandChild = expand.firstElementChild; // 第一个子元素的第一个子元素,用来监听变大 contract.scrollLeft = contract.scrollWidth; // 滚动到最右 contract.scrollTop = contract.scrollHeight; // 滚动到最下 expandChild.style.width = expand.offsetWidth + 1 + 'px'; // 保持宽度多1px expandChild.style.height = expand.offsetHeight + 1 + 'px'; // 保持高度多1px expand.scrollLeft = expand.scrollWidth; // 滚动到最右 expand.scrollTop = expand.scrollHeight; // 滚动到最右 };
/** * 检测触发器状态 * @param element 要检查的元素 * @returns {boolean} 是否改变了大小 */ const checkTriggers = function(element) { // 宽度或高度不一致就返回true return element.offsetWidth !== element.resizeLast.width || element.offsetHeight !== element.resizeLast.height; };
/** * 添加大小更改监听 * @param element 要监听的元素 * @param fn 回调函数 */ export const addResizeListener = function(element, fn) { if (isServer) return; // 服务器端直接返回 if (attachEvent) { // 处理低版本ie element.attachEvent('onresize', fn); } else { if (!element.resizeTrigger) { // 如果没有触发器 if (getComputedStyle(element).position === 'static') { element.style.position = 'relative'; // 将static改为relative } createStyles(); element.resizeLast = {}; // 初始化触发器最后的状态 element.resizeListeners = []; // 初始化触发器的监听器 const resizeTrigger = element.resizeTrigger = document.createElement('p'); // 创建触发器 resizeTrigger.className = 'resize-triggers'; resizeTrigger.innerHTML = '<p class="expand-trigger"><p></p></p><p class="contract-trigger"></p>'; element.appendChild(resizeTrigger); // 添加触发器 resetTrigger(element); // 重置触发器 element.addEventListener('scroll', scrollListener, true); // 监听滚动事件 /* Listen for a css animation to detect element display/re-attach */ // 监听CSS动画来检测元素显示或者重新添加 if (animationStartEvent) { // 动画开始 resizeTrigger.addEventListener(animationStartEvent, function(event) { // 增加动画开始的事件监听 if (event.animationName === RESIZE_ANIMATION_NAME) { // 如果是大小改变事件 resetTrigger(element); // 重置触发器 } }); } } element.resizeListeners.push(fn); // 加入该回调 } };
/** * 移除大小改变的监听 * @param element 被监听的元素 * @param fn 对应的回调函数 */ export const removeResizeListener = function(element, fn) { if (attachEvent) { // 处理ie element.detachEvent('onresize', fn); } else { element.resizeListeners.splice(element.resizeListeners.indexOf(fn), 1); // 移除对应的回调函数 if (!element.resizeListeners.length) { // 如果全部时间被移除 element.removeEventListener('scroll', scrollListener); // 移除滚动监听 element.resizeTrigger = !element.removeChild(element.resizeTrigger); // 移除对应的触发器,但保存下来 } } };
Others 一部のコンテンツは最適化のために使用されており、サーバー レンダリングとクライアント レンダリングの区別、IE の特殊な処理、不透明アニメーションによる Chrome のバグ解決などの基本的な機能には影響しません。
以上がJS はスクロールを使用して画像とテキストのサイズ変更の例を監視しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。