はじめに
スキルバーはネットにいっぱい情報が転がってるけど、
1.クリック動作だけとかスクロール設定までされてないもの
2.デザインにこだわりすぎてシンプルじゃないもの
3.ライブラリを使ってるもの
4.なぜか全部一緒に動くようにしてる。←ココが一番気になる
5.シンプルでそれぞれ別々で動くものがない
というスキルバーが結構あったので、
以下のようなスキルバーを作成すべくコーディング。
上記を解決するために、
1.シンプルで汎用的なもの
2.全部一緒に動かずに別々に動くもの(同じクラスを付与)
3.別ライブラリを使わずになるべく再現性や応用ができるもの
の3つにこだわって作成。
DEMOはこちら。
See the Pen
pojEJeY by 坊 拓磨 (@bo_chan6130)
on CodePen.
こんな感じで、
スクロールすれば可視領域でそれぞれのバーが動く、という仕組みを作ってみた。
(下記に解説を載せておきます。)
HTMLとCSSを準備
<script type="text/javascript"src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script><divclass="pro-box"><divclass="Progress_Status"><divclass="myprogressBar"></div><divclass="prorate"data-value="80">1%</div></div><divclass="Progress_Status"><divclass="myprogressBar"></div><divclass="prorate"data-value="60">1%</div></div><divclass="Progress_Status"><divclass="myprogressBar"></div><divclass="prorate"data-value="40">1%</div></div><divclass="Progress_Status"><divclass="myprogressBar"></div><divclass="prorate"data-value="20">1%</div></div></div>
[point]
バーと数字(%)を別で動作させる仕組みの方がかなり簡単だけど正直カッコよくないので
myprogressBarの長さは、直下の要素<div class="prorate" data-value="80">1%</div>
のdata-value=""
の値に応じて長さが決まるようにする。
.pro-box{margin-bottom:500px;margin-top:300px;/*スクロール用*/}.Progress_Status{width:100%;background-color:#fff;}.myprogressBar{width:1%;height:50px;background-color:#6babf1;text-align:center;display:inline-block;}.prorate{display:inline-block;vertical-align:top;height:50px;line-height:50px;margin-left:10px;}
バーの大きさやスタイル調整はお好みで。
jQueryで動作を制御
作成にあたってのミソ。
Ⅰ)スクロールして要素が可視領域に入れば「一度だけ」動作する
Ⅱ)同クラスから別々のdata-value
値をそれぞれ取得→動作させる
$(function(){$(window).scroll(function(){$(".myprogressBar:not(.fire)").each(function(){//eachで同一クラスmyprogressBarをそれぞれ取得varposition=$(this).offset().top;//それぞれ要素の位置を取得varscroll=$(window).scrollTop();//スクロール値を取得varwindowHeight=$(window).height();//画面サイズの高さを取得varelement=$(this);//barの長さに反映するために用意varprorate=$(this).next();//指定要素の2番目の要素<div class="prorate"></div>をnext()で指定。varvalue=prorate.data("value");//barの値を取得varwidth=1;//初期値を1に設定if(scroll>position-windowHeight){//可視領域設定。※高さを変えたい場合はwindowHeightの後ろを調整。+ 100 にすると画面下から100pxの高さで表示設定できる。varidentity=setInterval(scene,10);//setIntervalで関数を制御。バーの動きを遅くしたい場合は第2引数の数字を増やす。functionscene(){if(width>=value){clearInterval(identity);//value値まで数字が到達すればintervalをストップ。}else{$(element).addClass('fire');//それぞれの要素にfireクラスを付与。「一度だけ」行う関数の制御にはaddClassが有効。width++;element.width(width+'%');//barの長さ。value値の分だけ伸びる設定prorate.html(width*1+'%');//value値のカウント※html()でindex.htmlのテキスト「1%」を上書き)}}}})})})
[point]
ポイントは、「一度だけ処理」する場合はaddClass()を使って制御するということ。
今回の場合、最初はfire
クラスを持っていないmyprogressBar
をそれぞれ取得し、function scene(){}
を実行するときに、fire
クラスを持たせることで、$(window).scroll(function(){ }
以下のループ処理を実行不可にさせている。もし、この処理がない場合は、スクロールするたびにeachがループするので、思った挙動は起こらない。今回のように同一クラスを用いて別々に「一度だけ」実行処理する場合はaddClass()で制御する。
また、同一クラスでそれぞれの値を取得するときは、each(){}
の中身は必ず$(this)
で統一する。仮に$(".myprogressBar")
とした場合、ループは実行されず、最初の.myprogressBar
のみ値を取得する。そのため、一番上のバーのみ動き、他は動かくなるので注意が必要。
まとめ
scroll()
を使用するとスクロール度に動作が実行されるので、addClass()を使って動作制御をすることでうまくいく。また、このコードを参考に指定値までのカウンティングに応用できるはずなので、余力があればそちらも公開したい。