今回はこのような疑問に答えていきます。
jQueryでappendやprependで要素を追加した後にスクロールさせない(要素に移動させない)方法
先日、メッセージの追加読み込み機能を開発していたところ、「さらに読み込むボタン」を押してprependで追加すると、追加した要素にスクロールで移動してしまいました。
そこで、移動させないようなコードを書いたので紹介します。
実際のコード
HTML側のコードとJS側のコードをそれぞれ紹介します。
なお、HTML側はすでに動的に要素が追加された後のものとします。
(rowというクラスの要素を追加したとします。)
↓HTML
<div class="message-container" style="overflow: auto; height:24rem;"> //ここからスクロール要素
<div class="message-area">
<div class="message-body" id="scroll-content">
<div class="message-bodey-buttuon">
<div class="more-read-button text-center">
<button id="more-read-button-1">さらに読み込む</button>
</div>
</div>
<div class="all-content">
//動的に追加した部分 -- start --
<div class="row">
<span class="text-right block text-xs message-body-time">8:44</span>
<span class="text-right block message-body-content" id="message-id-1">おはよう</span>
</div>
//動的に追加した部分 -- end --
<div class="row">
<span class="text-right block text-xs message-body-time">8:44</span>
<span class="text-right block message-body-content" id="message-id-2">おはよよう</span>
</div>
<div class="row">
<span class="text-left block text-xs message-body-time">21:25</span>
<span class="text-left block message-body-content" id="message-id-3">テスト</span>
</div>
</div>
</div>
</div>
</div>
↓JS側
const scrollToElm = $( `#message-id-2` ).parent().position().top; //all-contentからの距離を取得
const buttonHeight = $( ".all-content" ).position().top; //message-bodyからの距離を取得
const nowScrollHeight = $( ".message-container" ).scrollTop(); //現在のスクロールの距離を取得
$( ".message-container" ).scrollTop( scrollToElm - buttonHeight + nowScrollHeight ); //要素追加前の位置にスクロールを移動させる
実装のポイントをいくつか解説していきます。
ポイント①:スクロールさせない→元の位置までスクロールするという発想に転換
「要素追加時にスクロールさせたくない」という考えを「要素追加後に元の位置までスクロールする」という発想に転換しました。
先程のJSのコードの「$( ".message-container" ).scrollTop....」の部分です。
ちなみに、scrollTopは引数として、位置の値を渡すとその位置までスクロールしてくれます。
Description: Set the current vertical position of the scroll bar for each of the set of matched elements.
ポイント②:親要素からの距離をうまく算出して、スクロールさせたい距離を出す
position()メソッドを使って、親要素からの距離を算出して、スクロールさせる距離を取得しました。
後は先程のscrollTopに渡してあげればOKです。
Description: Get the current coordinates of the first element in the set of matched elements, relative to the offset parent.
移動した分をスクロールで戻してあげるイメージを持つと良い
「スクロールさせない」とかではなく、シンプルに、動的な要素追加のイベントで追加された要素の距離分をスクロールで戻してあげるイメージを持つと実装しやすいかなと思いました。
僕自身は、その考えに至るまで少しハマってしまったので...。
よかったら参考にしてみてください。
今回は以上です。