BLOG ブログ


2023.08.24 TECH

スクロールイベントでパララックスさせる件@jQuery

とりあえず完成物

See the Pen scroll-event&parallax by nanba (@nanba) on CodePen.

強引に縮小表示してるので動きが少し悪いです…

実装の概要

本来ならIntersection Observer APIとか使ってスマートに解説したいところですが…今回はあくまでも視差効果の考え方・基本実装がメインな記事となりますので、ゴッリゴリのベッタベタなjQuery書いてます。
スクロールイベントで制御しているのは以下三点

  1. 指定要素がスクロールにて画面下部から50pxの位置にきたら発火 ※50pxマージンを設けたのは視野効果が見えないところで終わってしまうのを回避するため
  2. 立方体のパララックス効果
    スクロール依存速度制御/動的可動領域制御(該当要素+前1画面分) ※分かりやすいように全てcss@top値を制御
  3. コラージュCGの表示・非表示制御 ※1つ1つ設定するとあまりにも冗長になる懸念があったため等間隔制御にした ※個人差はあると思いますし自己満足的なアレですがマウス1クリクリで1枚画像が表示される速度感にしてますw

上記を実現させるために、下記をそれぞれ取得して算数してパララっています

  1. スクロール量
  2. ブラウザ画面高さ
  3. 指定要素の位置(スクロール量依存)
  4. 指定要素自体の高さ

指定要素がスクロールにて画面下部から50pxの位置にきたら発火

$(window).on('load scroll', function() {
  let windowH = $(window).height();
  let scrollT = $(window).scrollTop();
  $('該当要素').each(function(){
    const pos_trigger = $(this).offset().top;
    if (scrollT > pos_trigger - windowH + 50){
      $(this).addClass('js-switch_on');
    }else{
      $(this).removeClass('js-switch_on');
    }
  })
})
  1. windowHでブラウザ画面高さ取得
  2. scrollTでスクロール量取得
  3. pos_triggerで指定要素の位置取得(スクロール量依存)
  4. 指定要素が画面下部から50pxの位置に来たら、要素にjs-switch_onをトグル付与@L6~10
該当要素{
  margin-top:6em;
  opacity:0;
  transition:all .5s ease;
  &.js-switch_on{
    margin-top:0;
    opacity:1;
  }
}

class付与・削除のみ js にて制御して、アニメーション部分は css で実装しています。
この場合におけるtransitionは、リアルタイムでの逆再生的な動きも付けることが出来ますので、とても便利ですね!
animationだと、ON・OFFの2パターンを設定する必要があり、尚且つアニメーションしている最中に違うアクションが起こっても、逆再生することは出来ないので、インタラクティブサイト構築の初期設計段階でナニを使ってドウ動かすのかを決めておく必要がありますね。
例)全てjs制御/トリガーのみjs制御/全てcss制御など...

立方体のパララックス効果

$(window).on('load scroll', function() {
  let windowH = $(window).height();
  let scrollT = $(window).scrollTop();
  const pos_box = $('パララ親要素').offset().top;
  const h_box = $('パララ親要素').height();
  if(pos_box < scrollT + windowH && scrollT < pos_box + h_box){
// $('サンプル').css({top:(scrollT - pos_box) + 'px'}).fadeIn('1000');
    $('パララ要素A').css({top:(scrollT - pos_box) * 2 + windowH + 'px'}).fadeIn('1000');
    $('パララ要素B').css({top:(pos_box - scrollT) * 1.5 + (windowH / 3) + 'px'}).fadeIn('1000');
  }else{
    $('サンプル,パララ要素A,パララ要素B').fadeOut('1500');
  }
})
  1. windowHでブラウザ画面高さ取得
  2. scrollTでスクロール量取得
  3. pos_boxで指定要素の位置取得(スクロール量依存)
  4. h_boxで指定要素の高さ取得
  5. 各パララ要素を制御する範囲を指定@L6
  6. 上記範囲でのフェードトグル設定
  7. 各パララ要素位置を動的に制御(css:top値)

コメントアウトしてある7行目を例として解説します。
サンプル要素に対して、cssのtopを動的に制御してます。
この場合top:(scrollT - pos_box) + 'px'なので、パララ親要素が画面最下部に来た時点で、サンプル要素top:0pxがDOM的に付与され、さらにスクロールし続けるとスクロール量分だけサンプル要素のtop値がプラスされていきます。
ようするに見た目的にはブラウザ画面最上部に表示され続けます。
パララ親要素が画面上部から100px上にスクロールすると、サンプル要素にはtop:100pxが動的に付与され、結果的にposition:fixed: top:0;と同じくなりますね!
文章で説明すると物凄く分かりにくいですね…これ。
実際に組んでみたら、0.1秒で仕組みが理解できます!
これを基準に考え、あとは各パララ要素を【上に動かす】【下に動かす】【早く動かす】【ゆっくり動かす】をイイ感じに調整してあげたら、視差効果の完成です。
もちろん制御するのをleftにすれば横に動かすことも可能ですし、top・leftともに制御すれば斜めに動かすことも曲線的に動かすことも可能ですね。
三角関数などを使わなくても、これまで解説した内容をアレンジして算数すれば、イロイロな視差効果が創れるはずです^^

コラージュCGの表示・非表示制御

$(window).on('load scroll', function() {
  let windowH = $(window).height();
  let scrollT = $(window).scrollTop();
  $('.p-collage-element li').each(function(i){
    const pos_collage = $('.p-collage').offset().top;
    if(pos_collage < scrollT - (i * windowH * 0.15) + (windowH * 0.2)){
      $('.p-collage-element li').eq(24 - i).fadeIn('1000');
    }else{
      $('.p-collage-element li').eq(24 - i).fadeOut('1000');
    }
  })
})

構造的には.p-collage-elementというulタグに25枚の画像を配置してposition:fixedにて絶対位置表示させており、その親要素はheight:475vhという高さを持たせてあります。 ※高さ(475vh)はコラージュCG画像枚数・表示する際の速度感に応じて調整 あとはスクロール量に応じて、一枚づつ画像を表示・非表示制御しているだけです@L6~10
※このCG画像作成・スライス作業のみで1日は費やしました…
ぶっちゃけコーディング自体は2時間程度だったので、本末転倒な時間の使い方とも言える

まとめ

今回は『視差効果』に関する記事でしたが、ちょっとしたアイディアで、様々なインパクトのある表現が出来ると思っています。
その閃いたモノを、より効果的に具現化するために必要なのはスキルよりも、むしろ設計だと私は日頃から考えております。

  • 閲覧者がドウ操作したら、ナニがドレだけドウ動くのが効果的なのか?
  • 動かすエレメントに対して、逆再生の有無はドウすべきか?
  • 動かす速度感はドノ程度に設定するのがサイト特性に合致するのか?
  • javascript・cssの制御分担をドウ切り分けるか?
  • PC・スマホなどのデバイス対応はドウすべきか?

この閃きを、より効率的に、ストレスなく実装するには、手を動かす前に、ある程度の粒度でキッチリと設計しておくべきだと思います、ココに時間をかけることは結果的に最終的な工数を下げると断言できます。
実装がイメージできていたら、実作業的な手戻りを防ぎつつ、具体的な検証・調べものも効率的に出来るからですね٩(๑❛ᴗ❛๑)۶


一覧に戻る


LATEST ARTICLE 最新の記事

CATEGORY カテゴリー