序文
私が参加した2番目の会社から受け取った最初の要求は、以前に外部委託されていたローリングシーリング効果を修復することでした。スクロールする天井にバグがあるのはなぜだろうと思っていましたが、後でコードを確認したところ、属性offsetTopが直接使用されており、互換性の処理は行われていませんでした。
offsetTop
現在の要素から配置親(element.offsetParent)の上部までの距離(オフセット値)を取得するために使用されます。
親offsetParentの配置の定義は、次のとおりです。最も近い位置の親要素!=現在の要素に対して静的。
おそらく、このコードを書いた人は、「親を見つける」というサブ条件に気づいていませんでした。
後のプロジェクトでは、常に実現する必要のあるローリングシーリングの効果があります。次に、私が知っているローリングシーリングの4つの方法を詳しく紹介します。
目次
-
position:stickyを使用して達成する
-
JQueryのoffset()。top実装を使用する
-
ネイティブoffsetTop実装を使用する
- obj.getBoundingClientRect()。topを使用して
上記の4つの方法をすべて知っていますか?関連するコードがGitHub(https://github.com/wanqihua/The-dictionary-of-front-end-test)にアップロードされており、興味のある人はコードを複製してローカルで実行できます。スターのサポートをしたいと思っています。
達成するための4つの方法
1つは、位置を使用する:粘着性を実現する
1.スティッキーポジショニングとは何ですか?
スティッキーポジショニングスティッキーは、相対位置相対位置と固定位置固定の組み合わせに相当します。ページ要素のスクロールプロセスで、親要素からの要素の距離がスティッキーポジショニング要件に達すると、要素の相対位置の相対効果が固定位置になります。効果。
2.使い方は?
利用条件:
-
親要素はオーバーフロー:非表示またはオーバーフロー:自動属性を持つことはできません
-
上、下、左、右の4つの値のいずれかを指定する必要があります。指定しない場合は、相対的な位置になります。
-
親要素の高さは、スティッキー要素の高さより低くすることはできません
- スティッキー要素は、その親要素内でのみ有効になります
この効果は、スクロールと天井が必要な要素に次のスタイルを追加することで実現できます。
.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
}
3.この属性は使いやすいですか?
まず、「使用できますか」でこの属性の互換性を確認しましょう。
このAPIは実験的な属性にすぎないため、この属性の互換性はあまり良くないことがわかります。ただし、IOSシステムでのこのAPIの互換性はまだ比較的良好です。
したがって、このAPIを実稼働環境で使用する場合は、通常、次のメソッドと組み合わせて使用します。
次に、JQueryのoffset()。top実装を使用します
JQueryは、DOMを操作してDOM計算プロパティを読み取るためのAPIをカプセル化することを知っています。offset()。topとscrollTop()の組み合わせに基づいて、スクロール天井効果を実現することもできます。
...
window.addEventListener('scroll', self.handleScrollOne);
...
handleScrollOne: function() {
let self = this;
let scrollTop = $('html').scrollTop();
let offsetTop = $('.title_box').offset().top;
self.titleFixed = scrollTop > offsetTop;
}
...
これは確かに可能ですが、JQueryは歴史の段階から徐々に撤退しているため、コードでJQueryAPIを使用しないようにしています。offset()。topのソースコードに基づいて、ネイティブのoffsetTopを自分で処理できます。したがって、3番目の方法があります。
scrolloTop()には互換性の問題があります。WeChatブラウザー、IE、および一部のfirefoxバージョンでは、$( 'html')。scrollTop()の値は0になるため、3番目のスキームの互換性はほとんどありません。 。
第三に、ネイティブのoffsetTop実装を使用します
offsetTopは、配置する親に対するオフセットであることがわかっています。上にスクロールする必要がある要素が親要素に配置されているように見える場合、offsetTopは要素とページの上部との間の距離を取得しません。
offsetTopで次の処理を自分で行うことができます。
getOffset: function(obj,direction){
let offsetL = 0;
let offsetT = 0;
while( obj!== window.document.body && obj !== null ){
offsetL += obj.offsetLeft;
offsetT += obj.offsetTop;
obj = obj.offsetParent;
}
if(direction === 'left'){
return offsetL;
}else {
return offsetT;
}
}
使用する:
...
window.addEventListener('scroll', self.handleScrollTwo);
...
handleScrollTwo: function() {
let self = this;
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
let offsetTop = self.getOffset(self.$refs.pride_tab_fixed);
self.titleFixed = scrollTop > offsetTop;
}
...
上記の2つの方法に問題がありますか?
スクロール天井の効果を実現するには、scrollTop-offsetTopの値を使用する必要がありますか?答えは否定的です。
4番目のオプションを見てみましょう。
第4に、obj.getBoundingClientRect()。topを使用して
定義:
このAPIは、ブラウザウィンドウに対するページ上の要素の距離を知ることができます。
使用する:
タブの上限については、scrollTop-offsetTopの代わりにobj.getBoundingClientRect()。topを使用できます。コードは次のとおりです。
// html
<div class="pride_tab_fixed" ref="pride_tab_fixed">
<div class="pride_tab" :class="titleFixed == true ? 'isFixed' :''">
// some code
</div>
</div>
// vue
export default {
data(){
return{
titleFixed: false
}
},
activated(){
this.titleFixed = false;
window.addEventListener('scroll', this.handleScroll);
},
methods: {
//滚动监听,头部固定
handleScroll: function () {
let offsetTop = this.$refs.pride_tab_fixed.getBoundingClientRect().top;
this.titleFixed = offsetTop < 0;
// some code
}
}
}
offsetTopとgetBoundingClientRect()の違い
1. getBoundingClientRect():
ブラウザウィンドウに対するページ内の要素の左、上、右、下の位置を取得するために使用されます。ドキュメントのロールアップされた部分は含まれません。
この関数は、top、right、buttom、left、width、heightの6つの属性を持つオブジェクトオブジェクトを返します。(IEでは、デフォルトの座標は(2,2)から計算され、top、lef、right、bottomの4つの値のみが返されます)
2. offsetTop:
現在の要素から配置親(element.offsetParent)の上部までの距離(オフセット値)を取得するために使用されます。
親offsetParentの配置の定義は、次のとおりです。最も近い位置の親要素!=現在の要素に対して静的。
offsetTopメソッドとoffsetParentメソッドを組み合わせて、要素から本体の上部マージンまでの距離を取得します。コードは次のように表示されます。
getOffset: function(obj,direction){
let offsetL = 0;
let offsetT = 0;
while( obj!== window.document.body && obj !== null ){
offsetL += obj.offsetLeft;
offsetT += obj.offsetTop;
obj = obj.offsetParent;
}
if(direction === 'left'){
return offsetL;
}else {
return offsetT;
}
}
拡張された知識
offsetWidth:
水平方向に要素が占めるスペースのサイズ:
offsetWidth = border-left + padding-left + width + padding-right + border-right
offsetHeight:
垂直方向に要素が占めるスペースのサイズ:
offsetHeight = border-top + padding-top + height + padding-bottom + border-bottom
注:垂直スクロールバーがある場合、offsetWidthには垂直スクロールバーの幅も含まれます。水平スクロールバーがある場合、offsetHeightには水平スクロールバーの高さも含まれます。
offsetTop:
要素の上部外側境界とoffsetParent要素の上部内側境界の間のピクセル距離。
offsetLeft:
要素の左外側の境界からoffsetParent要素の左内側の境界までのピクセル距離。
予防
-
すべてのオフセット属性は読み取り専用です。
-
要素にdisplay:noneが設定されている場合、そのオフセット属性はすべて0です。
-
オフセット属性にアクセスするたびに、再計算(変数を保存)する必要があります。
- 使用中に、DOMが初期化されておらず、属性が読み取られているように見える場合があります。このとき、0が返されます。この問題では、DOM要素が初期化されるまで待ってから実行する必要があります。
発生した2つの問題
1.吸引の瞬間はジッターを伴う
ジッタの理由は、最上位の要素の位置が固定されると、その要素がドキュメントフローから外れ、次の要素が埋められるためです。ジッタを引き起こすのはこのビット充填操作です。
解決
この天井要素に同じ高さの親要素を追加します。この親要素のgetBoundingClientRect()。top値を監視して、天井効果を実現します。
<div class="title_box" ref="pride_tab_fixed">
<div class="title" :class="titleFixed == true ? 'isFixed' :''">
使用 `obj.getBoundingClientRect().top` 实现
</div>
</div>
このソリューションは、ジッターのバグを解決できます。
第二に、天井効果は時間内に応答することができません
この問題は私の頭痛の種です。以前は気にしませんでした。ある日Meituanを使ってテイクアウトを注文するまで、私はこの問題に注意を払いませんでした。
説明:
-
ページが下にスクロールするとき、ceiling要素は、ceiling効果が表示される前に、ページのスクロールが停止するのを待つ必要があります。
- ページを上にスクロールすると、天井要素にスクロールしてドキュメントフローの位置を復元するときに、天井要素は元の形状に戻りませんが、ページのスクロールが停止すると元の形状に戻ります。
理由:iosシステムではスクロール監視イベントをリアルタイムで監視できず、スクロールが停止すると関連イベントがトリガーされます。
解決:
位置を覚えています:最初のスキームで粘着性がありますか?この属性は、IOS6を超えるシステムとの互換性が高いため、IOSデバイスとAndroidデバイスを区別して2つの処理を実行できます。
IOSはposition:stickyを使用し、Androidはスクロールを使用してgetBoundingClientRect()。topの値を監視します。
IOSバージョンが低すぎる場合はどうなりますか?ここにアイデアがあります:window.requestAnimationFrame()。
フロントエンド辞書シリーズ
「フロントエンド辞書」シリーズは今後も更新されていきますので、毎号、頻繁に出てくる知識のポイントについてお話します。読んでいるうちに、文章のどこに厳密さや誤りがないのかを見つけていただければ幸いです。このシリーズから何かを手に入れていただければ幸いです。
内容:フロントエンドおよびネットワーク関連のナレッジポイントの紹介と、実用化を支援します。
目的:この一連の記事は、読者を少し助け、混乱を解決するのに役立ちます。
私はあなたが私にいくつかの指針を与え、私にアドバイスを与えることができることを願っています。
私の記事がうまく書かれていると思うなら、私に従ってください!