jQueryプラグイン「ScroolMagic」2系でよく使う機能を紹介します


jQueryプラグイン「ScroolMagic」2系でよく使う機能を紹介します

こんにちは、づやです。

前回ScrollMagic2系について下記の記事を書きましたが、基本的な使い方しか書けなかったので、今回はよく使う機能について書きたいと思います。

個人的にTweenMaxをよく使うので、animation.gsap.jsを読み込んでる状態での記事となります。

setClassToggle

スクロールの位置によってクラスを付けかえたいときは非常によくあるかと思います。そんなときは、スクロールに応じてクラスを付けたり外したりしてくれるsetClassToggleの出番。

<ul>
   <li id="list1"><a href="#block1">1番目</a></li>
   <li id="list2"><a href="#block2">2番目</a></li>
   <li id="list3"><a href="#block3">3番目</a></li>
</ul>
<section id="block1">
  ここにいろいろ書きます
</section>
<section id="block2">
 ここにいろいろ書きます
</section>
<section id="block3">
  ここにいろいろ書きます
</section>

styleは省略しますが、上記のようなマークアップをしておいて下のような記載をします。

// 全体を制御するコントローラをつくります。
var controller = new ScrollMagic.Controller();

// トリガーになる位置を指定してアニメーションを設定します。
var scene = new ScrollMagic.Scene({
			triggerElement: "#block1", // シーンで発火の対象となる要素を指定しましょう。
			duration :400 // スクロールの距離をpxで記載します(2系は%でもいけます)。
		})
		.setClassToggle("#list1", "active") // セレクタ,class名を渡します。対象のセレクタにトリガーのタイミングで対象のセレクタのクラスを付けたり外したりしてくれます。
		.addIndicators()
		.addTo(controller);

var scene2 = new ScrollMagic.Scene({
	triggerElement: "#block2",
	duration :400
})
		.setClassToggle("#list2", "active")
		.addIndicators()
		.addTo(controller);

var scene3 = new ScrollMagic.Scene({
	triggerElement: "#block3",
	duration :400
})
		.setClassToggle("#list3", "active")
		.addIndicators()
		.addTo(controller);

実際に書く場合はfor文とかを使ってもっとコンパクトに書けますが、1個1個書いていくとこんな感じになります。
このように書くことで、スクロールに応じて対象のliにactiveクラスを付けたり外したりしてくれます。当然liだけでなく、他の要素にクラスを付けたり外したりも可能です。
対象のクラスにtransitionを設定しておけばアニメーションをさせることもできるので、なかなか便利です。

enterとleave

setClassToggleはクラスの付け替えをしてくれますが、そうじゃなくて独自にもっといろいろおこないたいときもありますよね。
そんなときは、スクロールに応じて指定した動きをおこなえるイベントenterとleaveを設定することで実現できるようになります。

マークアップは先ほどの例と同じだとして、下記のような記載をします。

// 全体を制御するコントローラをつくります。
var controller = new ScrollMagic.Controller();

// トリガーになる位置を指定してアニメーションを設定します。
var scene = new ScrollMagic.Scene({
		triggerElement: "#block1", // シーンで発火の対象となる要素を指定します。
		duration :400 // 対象のスクロール距離です。設定しないとleaveが発火しない模様。
	})
	.on("enter" , function(e){ // triggerElement(と指定したtriggerHook)に到達したタイミングで呼ばれます。
		console.log("enter");
		console.log(e); // progress(0から1の間で現在のパーセンテージの値)などいろいろ入ってます。
	})
	.on("leave" , function(e){ // triggerElement(と指定したtriggerHook)の外に到達したタイミングで呼ばれます。
		console.log("leave");
		console.log(e); // enterのときとおんなじ情報がとれます。
	})
	.addIndicators()
	.addTo(controller);

動作の仕組み自体はsetClassToggleとほぼ同様ですが、独自に処理をかけるので用途が広がります。個人的にはprogressの値に応じて、何かを動かしたいときに使うことが多いです。

setTween

これは1系にもあったのでおなじみですが、スクロールに応じて指定したアニメーションを呼び出せるsetTweenです。
今回はSVGをスクロールに応じて書いてみたコードです。
※このコードはjQueryを使用しています。

<section id="block1">
	<svg version="1.1" id="sample_svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
	 y="0px" viewBox="0 0 84 22" enable-background="new 0 0 84 22" xml:space="preserve">
<g>
	<path d="M8.2,9.4c-0.6,1.3-1.4,2.5-2.4,3.6h12.4v6.9h-0.6V19H6.1v1H5.5v-6.5c-1.2,1.4-2.7,2.6-4.3,3.5c-0.1-0.1-0.3-0.4-0.4-0.5
		c2.9-1.7,5.5-4.3,6.8-7.1H1.3V8.8h18.5v0.6H8.2z M18.1,6H3V2.1h0.6v3.3h6.6V1h0.6v4.3h6.7V2.1h0.6V6z M6.1,13.7v4.7h11.5v-4.7H6.1z
		"/>
	<path d="M40.8,18.4V19H22.2v-0.6h8.2v-17h0.6v6.9h8.3v0.6h-8.3v9.4H40.8z"/>
	<path d="M61.7,7.2v0.6H43.3V7.2h8.9V5.7h-6V2.4h6V1h0.6v1.3h6.4v3.3h-6.4v1.5H61.7z M50.3,17.8c-1.7,0.9-4.3,1.7-6.4,2.2
		c-0.1-0.1-0.3-0.4-0.5-0.5c2.1-0.5,4.7-1.2,6.3-1.9L50.3,17.8z M59.3,16.9H46V9.2h13.3V16.9z M58.7,9.8h-12v1.7h12V9.8z M58.7,12.1
		h-12v1.7h12V12.1z M58.7,14.5h-12v1.8h12V14.5z M52.2,5.1V3h-5.4v2.1H52.2z M52.8,3v2.1h5.7V3H52.8z M55.2,17.6
		c2.4,0.6,4.9,1.3,6.5,1.9L61.1,20c-1.5-0.6-3.9-1.3-6.4-2L55.2,17.6z"/>
	<path d="M68.1,10.1c-0.9-0.7-2.5-1.6-3.9-2.2l0.4-0.5c1.4,0.6,3,1.5,3.8,2.2L68.1,10.1z M64.6,19c1-1.6,2.6-4.5,3.7-6.7l0.5,0.4
		c-1,2.2-2.5,4.9-3.6,6.8L64.6,19z M65.6,1.5c1.3,0.7,2.9,1.8,3.7,2.6l-0.4,0.5c-0.8-0.8-2.4-1.9-3.7-2.6L65.6,1.5z M83,14.7h-6.4
		V20h-0.6v-5.2h-6.3v-0.6h6.3v-4h-5.1V9.5h5.1V5.7h-5.7V5.1h7.6C78.6,4,79.6,2.2,80.1,1l0.7,0.3c-0.7,1.2-1.5,2.7-2.2,3.8h3.8v0.6
		h-5.8v3.8h5.3v0.6h-5.3v4H83V14.7z M74.2,4.9c-0.4-0.9-1.2-2.4-2.1-3.5l0.5-0.3c0.8,1.1,1.7,2.5,2.1,3.5L74.2,4.9z"/>
</g>
</svg>

</section>

こんな要素があったとして、pathに下記のようなstyleを当てておきます。

path {
  stroke: rgb(51, 98, 156);
  stroke-width:1;
  fill:none;
}

塗りつぶしなしのSVGを用意した状態にしています。

// pathのdasharrayを全部なくしておきます。
var $sampleSvgPaths = $("#sample_svg").find("path");
$sampleSvgPaths.each(function(){
	var len = $(this).get(0).getTotalLength();
	$(this).css({"strokeDasharray":len , "strokeDashoffset":len});
});

var tween = new TimelineMax()
		.add(TweenMax.to($sampleSvgPaths, 2 , {strokeDashoffset: 0, ease:Linear.easeNone}))

// 全体を制御するコントローラをつくります。
var controller = new ScrollMagic.Controller();

// トリガーになる位置を指定してアニメーションを設定します。
var scene = new ScrollMagic.Scene({
		triggerElement: "#sample_svg", // シーンで発火の対象となる要素を指定します。
		duration :400 ,
		tweenChanges : true // trueだとスクロールにあわせてアニメーションしてくれます。
							  // falseだとスクロール位置まで一気にtweenが動きます。
	})
	.setTween(tween) // 作ったtweenを設定します。
	.addIndicators()
	.addTo(controller);

最初にpathの長さを取得し、stroke-dasharrayとstroke-dashoffsetを同じ値にして、何も書き出されていない状態にします。そして、スクロールに応じさせたアニメーションをtween変数にいれます。
あとは、今までと同じようにシーンを作成して、setTweenに用意した変数tweenを指定するだけ。これでスクロールに応じてSNGが書き出されたり、消えていったりしてくれます。相変わらず便利ですね。

あとは、知らなかっただけかもしれませんが、tweenChangesという値がシーンに追加されていて、こいつをtrueにするとスクロールに応じてアニメーションを続けてくれます。説明が難しいですが、falseだとTweenLite.setで現在のパーセンテージのstyleを設定したときの動きになります。

さいごに

いかがでしたか?
自前で実装するとなかなか厄介なところがあるスクロール連動を簡単にできるのはいいですよね。
機会があれば、また違う使い方を書きたいと思います。

この記事を書いた人

づや
づや 取締役 2007年入社
高遠です。俺ほどずっとプログラム書いてるやつはいるかって、たぶんいないですね。LIGで唯一の闇属性です。好きな本は「ドグラマグラ」「ヴォイニッチ手稿」「旧約聖書」です。好きな思考実験は「シュレーディンガーの猫」。好きな言語はラテン語です。あと、嫌だったんですがLINEスタンプにもなりました。