マメな人はバカであれ

バカなりに考えて、バカなりに行動します

技術的なことや、趣味的なことや、私生活的なことを書いてきます

プラグインを使わないでパララックスをjsで実装

webページでパララックスの処理をjsで実装すると、それだけでもいい感じになったりしますよね。
それを実装するのに「Rellax.js」「Parallax.js」などのプラグインがありますよね。
プラグインは手軽で便利なんだけど、環境によってはエラーが起きて使えなかったり…
私はプラグインとかはそんな理由でなるべく使わないようにしていますね。

そんなわけで、今回はこのパララックス(Parallax)の処理をプラグインを使用せずにjs(jQuery)で実装してみます。

まずはコードから

まずは変数

/* --- Parallax --- */
var $paraObj = $(".js-parallax"); // パララックスする塊の要素
var paraBoxArr = []; 
var paraBoxTop = [];
var paraBox1Arr = [];
var paraBox2Arr = [];
var paraBox3Arr = [];
var para1stScroll = [];
var para2ndScroll = [];
var para3rdScroll = [];
var paraBoxNum = $paraObj.length;
var f_para = false;

スクロール処理ってスクロールするたびにイベント発火させちゃうので結構動作が重くなったりするんですよね。
まぁ今回の処理はそこまで重たくは無いと思うけど…
なので、配列に格納してそれを参照するようにして少しでも処理を軽くします。
管理が面倒になりますが、それでもやらないよりマシです。
f_paraは初回読み込みのフラグです。どんな処理でもこういうフラグは入れるようにしていますね。

次は初回に読み込むパララックス処理

/* -----------------------------------------------
 * Ready
 * ----------------------------------------------- */
$(document).ready(function() {
  parallaxInit();
});

function parallaxInit() {
  if(!f_para){
    f_para = true;
    $paraObj.each(function(i, ele) { // パララックスする要素の塊を探す
      var $this = $(ele);
      paraBoxArr[i] = $this; // パララックスの指標となる要素
      paraBoxTop[i] = $this.offset().top; // パララックスの指標とするoffsetの高さ
      paraBox1Arr[i] = [];
      paraBox2Arr[i] = [];
      paraBox3Arr[i] = [];


      para1stScroll[i] = (paraBoxTop[i] - _sTop) * 0.1 + (paraBoxArr[i].height() / 30); // パララックスする要素一つ目のスクロール変化量
      para2ndScroll[i] = (paraBoxTop[i] - _sTop) * 0.2 + (paraBoxArr[i].height() / 30); // パララックスする要素二つ目のスクロール変化量
      para3rdScroll[i] = (paraBoxTop[i] - _sTop) * 0.3 + (paraBoxArr[i].height() / 30); // パララックスする要素三つ目のスクロール変化量

      $this.find(".js-p_first").each(function(index, el) {
        var $p_this = $(el);
        paraBox1Arr[i][index] = $p_this; // パララックスする要素一つ目

        $p_this[0].style.transform = 'translateY(' + String(para1stScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });
      $this.find(".js-p_second").each(function(index, el) {
        var $p_this = $(el);
        paraBox2Arr[i][index] = $p_this; // パララックスする要素二つ目

        $p_this[0].style.transform = 'translateY(' + String(para2ndScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });
      $this.find(".js-p_third").each(function(index, el) {
        var $p_this = $(el);
        paraBox3Arr[i][index] = $p_this; // パララックスする要素三つ目

        $p_this[0].style.transform = 'translateY(' + String(para3rdScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });

    });
  }
}

初回読み込み時のパララックスの処理です。
一応readyイベントを書いていますけど、タイミングは各々で決めてくださいね。

処理は、まずパララックスする大きな括りの要素をeachで探して、
その中にあるパララックスさせる要素を参照して配列に格納。
それらのoffsetの高さとスクロール量から、パララックスさせる変化量をpara1stScrollなどに格納。
ここの計算ですが、paraBoxTopは大きな括りの要素のoffsetの高さを格納していて_sTopのスクロール量との差を求め変化の度合いを0 < x < -1の小数を掛け算します。
スクロールの変化の度合いを調整するためにある程度の値を足してあげます。(ここでは大きな括りの要素の高さを適当な値で商を取っています)
この辺りの計算は多分もっといい感じのものがあると思いますので、各々調整してもらえればと。
(いい感じのができたら教えてください)
計算したパララックスの変化量para1stScrollなどはtransform: translateYにpxとして入れます。
$("object").css()とかでスタイルを入れるのもできますが、
その場合.css()は元々jQueryの処理なので毎回呼び出されるたびにjQueryを通さなきゃいけなくなってしまいます。
だもんで、object参照するようにしています。
(ここまでの処理でjQueryを使用しているのになんで!?って怒るかもしれませんが、この処理が意外と重いんですよね)

あと、今回はtransform: translateYとしていますが、ここは各々適当なスタイルを当てるようにしてください。

スクロール時の処理

/* -----------------------------------------------
 * - スクロール - 
 * ----------------------------------------------- */
$window.on('scroll', function (e) {
  e.preventDefault();
  _sTop = document.body.scrollTop || document.documentElement.scrollTop;

  /*  Parallax */
  if (!_SP && f_para) {
    for (var i = 0; i < paraBoxNum; i++) {

      para1stScroll[i] = (paraBoxTop[i] - _sTop) * 0.1 + (paraBoxArr[i].height() / 30); // パララックスする要素一つ目のスクロール変化量
      para2ndScroll[i] = (paraBoxTop[i] - _sTop) * 0.2 + (paraBoxArr[i].height() / 30); // パララックスする要素二つ目のスクロール変化量
      para3rdScroll[i] = (paraBoxTop[i] - _sTop) * 0.3 + (paraBoxArr[i].height() / 30); // パララックスする要素三つ目のスクロール変化量


      $.each(paraBox1Arr[i], function(index, ele) { // パララックスする要素一つ目配列を参照
        var $this = $(ele);
        paraBox1Arr[i][index][0].style.transform = 'translateY(' + String(para1stScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });
      $.each(paraBox2Arr[i], function(index, ele) { // パララックスする要素二つ目配列を参照
        var $this = $(ele);
        paraBox2Arr[i][index][0].style.transform = 'translateY(' + String(para2ndScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });
      $.each(paraBox3Arr[i], function(index, ele) { // パララックスする要素三つ目配列を参照
        var $this = $(ele);
        paraBox3Arr[i][index][0].style.transform = 'translateY(' + String(para3rdScroll[i]) + 'px)'; // transformのtranlsateYを使ってパララックスさせる
      });
    }
  }
});

スクロールでの処理は先に説明した処理のほんと中身の部分をそのまま使用しています。
唯一違うのは、先に格納した配列を用いているというところでしょう。
ここで配列を使わず再度参照するのと、配列に格納したものを使うのとでは処理の重さが違うと思います。
(検証はあまりしていないけど、体感的に軽いはず)

一応html

<div class="block js-parallax">
    <div class="block_node js-p_first">~~~</div>
    <div class="block_node js-p_second">~~~</div>
    <div class="block_node js-p_third">~~~</div>
</div>

書く必要もあるわからないけど、htmlでのclass名振り分けはこんな感じ。
大きい括りのjs-parallax、パララックスさせる要素がjs-p_first js-p_second js-p_thirdですね。
$(".js-parallax").find()で参照しているので一つ下の子である必要はないですし、その辺りも調整すればどうとでもなります。

終わり

配列の仕組みはプログラミングを嗜んでいる人なら誰でもわかる話ですが、
疎い人だと少し困惑するかもしれませんね。objectなんかも同様に。
でもここら辺を知っているだけでも、プログラミングは幅が広がっていきますので覚えておいた方が良いです。

今回のように、毎回$(".object")でDOMを参照して処理を書くのはスマートでは無いですし、動作も重くなってしまいがちです。
配列にDOMなどを格納して処理するだけでも、動作は軽くなります。
特にスクロールイベントはスクロールするたびに発火するので、処理の呼び出しがものすごい数になります。
そういった時にこうした方法を使えば多少なりとは軽くなるんじゃないでしょうか。

今まで食中毒や体調不良、短期旅行などをしていたもんで、山登りも写真も全く出来てないしネタもない状態でした…
最近じゃvTuberばかり観てます。私もモデリングして試しにやってみようかな、なんて思ったり。