お寿司か焼き肉食べたい

まじめな事からしょーもない事まで

なんか変な感じがするー!

パララックスサイト、視覚効果なんて言葉もありますが
結構使われている技術。LPで使われているパターンが多くを占めるのではないでしょうか。
まぁ、簡単に実装できるテンプレートやらなんやらはその辺に転がっていますが
やっぱそれは、どんな構造で動いているのかを知ってから使いたいものです。

パララックスサイトって?

若干の動きに差を持たせることで、お?みたいな感覚が起こる感じまぁ、つまり視覚効果ってコトなんですけどね!
単純なものからスタートして徐々にいい感じになるよう仕上げれたらいいなぁとか思ってます。

パララックスその1

単純に、要素が画面上でストップして、下の要素がどんどこ重なっていくそんな画面のをやってみましょう。
早速ですが→パララックスデモ

htmlの構造

基本的には普通にぺしぺし組んでいけばいいと思います。

<section id="box1">
 <!-- コンテンツ -->
</section>
<section id="box2">
 <!-- コンテンツ -->
</section>
<section id="box3">
 <!-- コンテンツ -->
</section>

別にsectionである必要はこれっぽっちもないです。

cssの構造

section{
  height: 700px;
}

#elem1{
  background: url('../img/1.jpg') no-repeat;
  background-size: cover;
  background-position: 0 0;
}

#elem2{
  background: url('../img/2.jpg') no-repeat;
  background-size: cover;
  background-position: 0 0;
}

#elem3{
  background: url('../img/3.jpg') no-repeat;
  background-size: cover;
  background-position: 0 0;
}

実はここでもそんなに・・・・なんですね。へっへ。

JSの構造

var elem1Data = {
      'domObj':$('#elem1'),
      'elemMovePos':0
    },
    elem2Data = {
      'domObj':$('#elem2'),
      'elemMovePos':parseInt($('#elem2').offset().top)
    },
    elem3Data = {
      'domObj':$('#elem3'),
      'elemMovePos':parseInt($('#elem3').offset().top)
    };

$(window).on("scroll",function()
{
  var y = $(this).scrollTop();
  
  if(y > elem1Data.elemMovePos){
    elem1Data.domObj.css('background-position','left ' + (y-elem1Data.elemMovePos) +'px');
  }else{
    elem1Data.domObj.css('background-position','left top');
  }
  
  if(y > elem2Data.elemMovePos){
    elem2Data.domObj.css('background-position','left ' + (y-elem2Data.elemMovePos) +'px');
  }else{
    elem2Data.domObj.css('background-position','left top');
  }
  
  if(y > elem3Data.elemMovePos){
    elem3Data.domObj.css('background-position','left ' + (y-elem3Data.elemMovePos) +'px');
  }else{
    elem3Data.domObj.css('background-position','left top');
  }
})

メインのJS部分です。
基本的にscrollのイベント内であれこれやってます。
考え方としては
【スクロール位置が各要素の絶対位置を超えた時に処理をする】
【背景画像の位置をスクロールと同じ分逆に動かす】
とすることで、画面上部にひっついたまま、次の要素が上にのっかるような効果を出すことができます。

パララックスその2

続いて、スクロールにあわせて背景がスススッっと動いていく形を実装してみます。
htmlとCSSは省略してJSだけで。
パララックスデモその2

var elem1Data = {
      'domObj':$('#elem1'),
      'elemMovePos':0,
      'offY':$('#elem1').offset().top,
      'offX':$('#elem1').offset().left
    },
    elem2Data = {
      'domObj':$('#elem2'),
      'elemMovePos':parseInt($('#elem1_2').offset().top)-200,
      'offY':$('#elem2').offset().top,
      'offX':$('#elem2').offset().left
    },
    elem3Data = {
      'domObj':$('#elem3'),
      'elemMovePos':parseInt($('#elem3').offset().top),
      'offY':$('#elem3').offset().top,
      'offX':$('#elem3').offset().left
    };
elem1Data.domObj.css('background-position','left -200px');
var y = 0;
var y2 = 1;
$(window).on("scroll",function()
{
  y = $(this).scrollTop();
  if(y > elem1Data.elemMovePos)
  {
    elem1 = ((parseInt(y)-parseInt(elem1Data.elemMovePos))*1.1)-200;
    elem1Data.domObj.css('background-position','left ' + elem1 +'px');
  }else{
    elem1Data.domObj.css('background-position','left -200px');
  }
  
  if(y > elem2Data.elemMovePos)
  {
    elem2 = ((parseInt(y)-parseInt(elem2Data.elemMovePos))*-0.3);
    elem2Data.domObj.css('background-position','left ' + elem2 +'px');
  }else{
    elem2Data.domObj.css('background-position','left top');
  }
  
  if(y > elem3Data.elemMovePos){
    elem3Data.domObj.css('background-position','left ' + (y-elem3Data.elemMovePos) +'px');
  }else{
    elem3Data.domObj.css('background-position','left top');
  }
})

基本的に、background-positionを触るのは変わりません。
今回少し変わっているのは、ずばりbackground-positionをセットする所。
適当な数字をかけてスクロール量より増減した数値をセットしています。
正数をかけることにより【スクロールと同じ方向に違うスピードで背景位置変更】
負数をかけることにより【スクロールと逆方向に違うスピードで背景位置変更】
の動きが実現できます。
当然かける数値が大きいほどたくさん動きます。

パララックスその3

さて、この3つ目のパララックス。文字に起こすのが難しいですね。
本気でなんて説明したらいいか分からない事案
パララックスデモその3
このパターンはJSを使いません。CSSだけで終わらせることができます。

section{
  height: 500px;
}

#elem0{
  height: 300px;
}

#elem1{
  background: url('../img/1.jpg') no-repeat;
  background-size: cover;
  background-position: 0 0;
  background-attachment: fixed;
}
#elem2{
  background: url('../img/2.jpg')  no-repeat;
  background-size: cover;
  background-position: 0 0;
  background-attachment: fixed;
}
#elem3{
  background: url('../img/3.jpg') no-repeat;
  background-size: cover;
  background-position: 0 0;
  background-attachment: fixed;
}

はい。background-attachment:fixedを指定して背景位置は固定~そんなレベルでOKです。

パララックスその4

さてスクロールさせた時に要素やらなんやらの動作速度が違うだけでそれなりの効果が期待できます。 パララックスデモその4

//------------------------------------------
// 初期値設定
//------------------------------------------
var windowElem  = $(window),
    windowWidth = windowElem.innerWidth(),
    contentheightEnd   = $('#elem1').outerHeight(),
    contentheightStart = $('#elem0').outerHeight(),
    elemCnt = 300,
    typeCnt = 3,
    bpxCnt = 6,
    elemsT1 = [],
    elemsT2 = [],
    elemsT3 = [],
    elemsT1C = 0,
    elemsT2C = 0,
    elemsT3C = 0;

//------------------------------------------
// 要素設定
//------------------------------------------
for(i=elemCnt;i>0;i--)
{
  // elemCnt分要素を作る
  typeR = 1 + Math.floor( Math.random() * typeCnt );
  switch(typeR){
    case 1:
      if(elemsT2C < 50){
        typeR = 2;
        elemsT2C++;
      } else if(elemsT3C < 30){
        typeR = 3;
        elemsT3C++;
      }
      break;
    case 2:
      if(elemsT2C < 50){
        elemsT2C++;
      } else if(elemsT3C < 30){
        typeR = 3;
        elemsT3C++;
      } else {
        typeR = 1;
        elemsT1C++;
      }
      break;
    case 3:
      if(elemsT3C < 30 ){
        elemsT3C++;
      }else if(elemsT2C < 50){
        typeR = 2;
        elemsT2C++;
      } else {
        typeR = 1;
        elemsT1C++;
      }
      break;
  }

  boxR = 1 + Math.floor( Math.random() * bpxCnt );
  topR = contentheightStart + Math.floor( Math.random() * contentheightEnd );
  leftR = Math.floor( Math.random() * windowWidth );
  switch(typeR){
    case 1:
      elemsT1.push("
 
"); break; case 2: elemsT2.push("
 
"); break; case 3: elemsT3.push("
 
"); break; } } $('#elem1').children('.type1box')[0].innerHTML = elemsT1.join(""); $('#elem1').children('.type2box')[0].innerHTML = elemsT2.join(""); $('#elem1').children('.type3box')[0].innerHTML = elemsT3.join(""); windowElem.on("scroll",function() { y = $(this).scrollTop(); $('.type1box').each(function() { type1Y = (y*-2)+1500; $(this).css({'top':+type1Y+'px'}); }); $('.type2box').each(function() { type1Y = (y*-1)+1000; $(this).css({'top':+type1Y+'px'}); }); $('.type3box').each(function() { type1Y = (y*-0.5); $(this).css({'top':+type1Y+'px'}); }); })

なんかそれっぽいすね!
ひとまず自力でここまで組めればなんとなく動きは理