検索
ホームページウェブフロントエンドjsチュートリアルSticky コンポーネントの改善された実装に関する簡単な説明_JavaScript スキル

前の記事getBoundingClientRect メソッドを使用して単純なスティッキー コンポーネントを実装する では、スティッキー コンポーネントの単純な実装を紹介しましたが、ここ 2 日間考えた結果、さらに多くの実装が提供されていることがわかりました。欠点は、前回提供した修正方法が不十分だったことを踏まえて、他の Web サイトで得られる効果が若干異なることです。この記事では、スティッキー コンポーネントの改良版を提供します。完了しました。興味を持って読んでいただければ幸いです。

1. 古いバージョンの問題

前のスティッキーコンポーネントの実装には複数の問題があります:

まず、スティッキーの効果についてですが、スティッキー要素を修正する前と後で変化しないのは、ブラウザの左側からの相対的な位置と、スティッキー要素の全体の幅です。ブラウザの上部または下部を基準とした位置とスティッキー要素の高さ。後者の 2 つの変化する値は定数値とみなされます。上限値または下限値が固定されているのに常に 0 になるのはなぜですか?もちろん、上: 20px、下: 15px など、0 以外の値にすることもできます。ブートストラップの公式ドキュメントで使用されている接辞コンポーネントの例のように、シーンによっては、そのようなオフセットを追加すると、スティッキー効果がより良く見えます。コンポーネント この機能は、この記事で実装されているスティッキー コンポーネントに似ています):

固定時はブラウザ上部からの相対位置をtop:20pxに設定します。スティッキー要素の高さについても同様であり、固定したときに見栄えの良い効果を表示するには、元の Line-height や Padding-top などの高さ関連の属性を調整することが非常に一般的です。 Tmall Huabei のこのページ、このブロック コンテンツはスティッキー コンポーネントを使用しています:

固定される前のスティッキー要素の高さは次のとおりです:

固定後のスティッキー要素の高さは次のとおりです:

2番目に、固定を解除する場合、上部に固定されているスティッキー要素を例にとります。上記の実装では、ターゲット要素とブラウザの上部の間の距離が離れたときに、スティッキー要素の位置を直接キャンセルします。 StickyHeight: 固定属性より小さい場合、sticky 要素は直ちに通常のドキュメント フローに復元され、その効果は次のとおりです:

臨界点に達するとすぐに消えますが、天猫花北の効果は次のようなものではありません:

臨界点に達してもすぐには消えませんが、スクロール バーと連動して Web ページのメイン コンテンツと一緒に上にスクロールできるように、スティッキー要素の上部の値を再調整します。

経験の観点から、Tmall Huabei の効果が優れていることは明らかです。機能の観点からは、上記の実装には致命的な欠点があります。スティッキー要素の高さが非常に大きい場合、ブラウザの能力を超えているため、どのようにスクロールしてもスティッキー要素の内容をすべて閲覧できないというバグが発生します。興味がある場合は、前回実装したコードを試してみてください。ブログのサイドバー。試してみたところこの問題が見つかったので、sticky コンポーネントを改善したいと思いました: (
第三に、最後の実装にはまだいくつかの欠点があります:

1) documentElement.clientHeight はキャッシュされないため、重要なポイントが判断されるたびに再取得されます:

2) スクロール コールバック間隔のデフォルト値は大きすぎるため、今回は 5 に設定し、ブートストラップでは 1 を使用します。この方法でのみ効果が保証されます。

3) 一部のシナリオでは、サイズ変更が必要な場合にスティッキー要素の幅をリセットする必要がない場合があります。それを制御するためのオプションを追加する必要があります。

4) スティッキー要素が固定されている場合と固定されていない場合、他のコンポーネントがこのコンポーネントに依存するときに重要なポイントで処理できるように、コールバック関数を提供する必要があります。

2. 改善方法

コンポーネントのオプションが再定義されました:

var DEFAULTS = {
target: '', //target元素的jq选择器
type: 'top', //固定的位置,top | bottom,默认为top,表示固定在顶部
wait: 5, //scroll事件回调的间隔
stickyOffset: 0, //固定时距离浏览器可视区顶部或底部的偏移,用来设置top跟bottom属性的值,默认为0
isFixedWidth: true, //sticky元素宽度是否固定,默认为true,如果是自适应的宽度,需设置为false
getStickyWidth: undefined, //用来获取sticky元素宽度的回调,在不传该参数的情况下,stickyWidth将设置为sticky元素的offsetWidth
unStickyDistance: undefined, //该参数决定sticky元素何时进入dynamicSticky状态
onSticky: undefined, ///sticky元素固定时的回调
onUnSticky: undefined ///sticky元素取消固定时的回调
};

太字のものは新規または変更されたもので、元の高さが削除され、unStickyDistance に置き換えられています。固定する場合はstickyOffsetでブラウザの上部または下部からの相対位置を指定するため、.sticky--in-topや.sticky--inのcssにtopやbottomの属性値を記述する必要はありません。 -底。 isFixedWidth が false の場合、サイズ変更中にスティッキー要素の幅を更新するためのコールバックが追加されます:


!opts.isFixedWidth && $win.resize(throttle(function () {
setStickyWidth();
$elem.hasClass(className) && $elem.css('width', stickyWidth);
sticky();
}, opts.wait));

前回と比べて今回の実装で問題となったのは、固定を解除する際の論理処理です。前回はsticky要素がstickyとunstickyの2つの状態に分かれていました。 staticStickyとdynamicStickyで、前者は上値または下値が変わらないスティッキー状態を表し、後者は上値または下値が変化するスティッキー状態を表します。この問題をより明確に解決するために、本来の判断は、クリティカル ポイントと、異なるクリティカル ポイントで異なる処理を実行するコードを次のように再構成します。

setSticky = function () {
!$elem.hasClass(className) && $elem.addClass(className).css('width', stickyWidth)
&& (typeof opts.onSticky == 'function' && opts.onSticky($elem, $target));
return true;
},
states = {
staticSticky: function () {
setSticky() && $elem.css(opts.type, opts.stickyOffset);
},
dynamicSticky: function (rect) {
setSticky() && $elem.css(opts.type, rules[opts.type].getDynamicOffset(rect));
},
unSticky: function () {
$elem.hasClass(className) && $elem.removeClass(className).css('width', '').css(opts.type, '')
&& (typeof opts.onUnSticky == 'function' && opts.onUnSticky($elem, $target));
}
},
rules = {
top: {
getState: function (rect) {
if (rect.top < 0 && (rect.bottom - unStickyDistance) > 0) return 'staticSticky';
else if ((rect.bottom - unStickyDistance) <= 0 && rect.bottom > 0) return 'dynamicSticky';
else return 'unSticky';
},
getDynamicOffset: function (rect) {
return -(unStickyDistance - rect.bottom);
}
},
bottom: {
getState: function (rect) {
if (rect.bottom > docClientHeight && (rect.top + unStickyDistance) < docClientHeight) return 'staticSticky';
else if ((rect.top + unStickyDistance) >= docClientHeight && rect.top < docClientHeight) return 'dynamicSticky';
else return 'unSticky';
},
getDynamicOffset: function (rect) {
return -(unStickyDistance + rect.top - docClientHeight);
}
}
}
$win.scroll(throttle(sticky, opts.wait));
function sticky() {
var rect = $target[0].getBoundingClientRect(),
curState = rules[opts.type].getState(rect);
states[curState](rect);
}
そこには状態モデルの考え方が少し含まれていますが、より簡潔です。このコードを書いたとき、私は以前に学んだステート マシンを使用したかったのですが、ステート マシンを使用してそれを書くことは確かに可能だと思いましたが、参照されないようにするためのクラス ライブラリを 1 つだけ作成したかったのです。いつかステートマシンを練習したいときにもう一度試してください。

全体的な実装は次のとおりです:

var Sticky = (function ($) {
function throttle(func, wait) {
var timer = null;
return function () {
var self = this, args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
return typeof func === 'function' && func.apply(self, args);
}, wait);
}
}
var DEFAULTS = {
target: '', //target元素的jq选择器
type: 'top', //固定的位置,top | bottom,默认为top,表示固定在顶部
wait: 5, //scroll事件回调的间隔
stickyOffset: 0, //固定时距离浏览器可视区顶部或底部的偏移,用来设置top跟bottom属性的值,默认为0
isFixedWidth: true, //sticky元素宽度是否固定,默认为true,如果是自适应的宽度,需设置为false
getStickyWidth: undefined, //用来获取sticky元素宽度的回调,在不传该参数的情况下,stickyWidth将设置为sticky元素的offsetWidth
unStickyDistance: undefined, //该参数决定sticky元素何时进入dynamicSticky状态
onSticky: undefined, ///sticky元素固定时的回调
onUnSticky: undefined ///sticky元素取消固定时的回调
};
return function (elem, opts) {
var $elem = $(elem);
opts = $.extend({}, DEFAULTS, opts || {}, $elem.data() || {});
var $target = $(opts.target);
if (!$elem.length || !$target.length) return;
var stickyWidth,
setStickyWidth = function () {
stickyWidth = typeof opts.getStickyWidth === 'function' && opts.getStickyWidth($elem) || $elem[0].offsetWidth;
},
docClientHeight = document.documentElement.clientHeight,
unStickyDistance = opts.unStickyDistance || $elem[0].offsetHeight,
setSticky = function () {
!$elem.hasClass(className) && $elem.addClass(className).css('width', stickyWidth)
&& (typeof opts.onSticky == 'function' && opts.onSticky($elem, $target));
return true;
},
states = {
staticSticky: function () {
setSticky() && $elem.css(opts.type, opts.stickyOffset);
},
dynamicSticky: function (rect) {
setSticky() && $elem.css(opts.type, rules[opts.type].getDynamicOffset(rect));
},
unSticky: function () {
$elem.hasClass(className) && $elem.removeClass(className).css('width', '').css(opts.type, '')
&& (typeof opts.onUnSticky == 'function' && opts.onUnSticky($elem, $target));
}
},
rules = {
top: {
getState: function (rect) {
if (rect.top < 0 && (rect.bottom - unStickyDistance) > 0) return 'staticSticky';
else if ((rect.bottom - unStickyDistance) <= 0 && rect.bottom > 0) return 'dynamicSticky';
else return 'unSticky';
},
getDynamicOffset: function (rect) {
return -(unStickyDistance - rect.bottom);
}
},
bottom: {
getState: function (rect) {
if (rect.bottom > docClientHeight && (rect.top + unStickyDistance) < docClientHeight) return 'staticSticky';
else if ((rect.top + unStickyDistance) >= docClientHeight && rect.top < docClientHeight) return 'dynamicSticky';
else return 'unSticky';
},
getDynamicOffset: function (rect) {
return -(unStickyDistance + rect.top - docClientHeight);
}
}
},
className = 'sticky--in-' + opts.type,
$win = $(window);
setStickyWidth();
$win.scroll(throttle(sticky, opts.wait));
!opts.isFixedWidth && $win.resize(throttle(function () {
setStickyWidth();
$elem.hasClass(className) && $elem.css('width', stickyWidth);
sticky();
}, opts.wait));
$win.resize(throttle(function () {
docClientHeight = document.documentElement.clientHeight;
}, opts.wait));
function sticky() {
var rect = $target[0].getBoundingClientRect(),
curState = rules[opts.type].getState(rect);
states[curState](rect);
}
}
})(jQuery);
理解するのが難しいのは、getState メソッドのロジックかもしれません。この部分のアイデアの一部は、前のブログで詳しく説明されています。

3. ブログサイドバーの適用手順

まず、この実装をブログ設定のフッター HTML テキスト フィールドに貼り付けてから、次のコードを追加して初期化する必要があります:


var timer = setInterval(function(){
if($('#blogCalendar').length && $('#profile_block').length && $('#sidebar_search').length) {
new Sticky('#sideBar', {
target: '#main',
onSticky: function($elem, $target){
$target.css('min-height',$elem.outerHeight());
$elem.css('left', '65px');
},
onUnSticky: function($elem, $target){
$target.css('min-height','');
$elem.css('left', '');
}
});
}
},100);
サイドバーのコンテンツは ajax によってロードされ、これらの ajax リクエスト中にコールバックを追加することはできないため、タイマーが使用されます。サイドバーがロードされたかどうかは、返されるコンテンツを通じてのみ判断できます。

4. 概要

この週末は、スティッキー コンポーネントを改善する方法を考えて、一日のほとんどをこの記事の執筆に費やしました。少なくとも、最後に書き終えたスティッキー コンポーネントの機能と実装には少し満足しています。何かが欠けているように奇妙に感じましたが、それはまだ多くのものが欠けているためであることがわかりました。現時点では、このコンポーネントは固定と固定解除の効果しか実現できません。固定された状態でナビゲーションのスクロールやタブのナビゲーションをサポートするインターネット上の一般的な機能も、このレベルの効果では十分ではない可能性があります。次へ この記事では、この記事を元に Sticky コンポーネント、navScrollSticky コンポーネントと tabSticky コンポーネントの実装方法を紹介しますので、ご期待ください。

読んでいただきありがとうございます:)

補足説明: IE および Firefox では、ページを更新するときに、更新前にページがスクロールしている場合、更新操作によってページのスクロール位置が更新位置に設定されますが、スクロール イベントはトリガーされないため、スクロール イベントの直後に呼び出す必要があります。コンポーネントは初期化されます:

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
CおよびJavaScript:接続が説明しましたCおよびJavaScript:接続が説明しましたApr 23, 2025 am 12:07 AM

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

Webサイトからアプリまで:JavaScriptの多様なアプリケーションWebサイトからアプリまで:JavaScriptの多様なアプリケーションApr 22, 2025 am 12:02 AM

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Python vs. JavaScript:ユースケースとアプリケーションと比較されますPython vs. JavaScript:ユースケースとアプリケーションと比較されますApr 21, 2025 am 12:01 AM

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

JavaScript通訳者とコンパイラにおけるC/Cの役割JavaScript通訳者とコンパイラにおけるC/Cの役割Apr 20, 2025 am 12:01 AM

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

JavaScript in Action:実際の例とプロジェクトJavaScript in Action:実際の例とプロジェクトApr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!