Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

【JavaScript】画面スクロールにあわせてCSS指定内容の変化

 どうも!LSSです!!

 

よく見かける内容ですが、CSSだけでは実装ができない、もしくは難しく、JavaScriptと組み合わせて実現する仕組みを作ってみました。

 

 

スクロールに応じた変化

画面スクロールにあわせてCSS指定が変化します。

 

 

コード

<div id="gamen">画面スクロールにあわせてCSS指定が変化します。</div>
<script>
document.addEventListener('scroll',fscr,false);
function fscr(){
a=100-(Math.min(Math.max(gamen.getBoundingClientRect().top,200),600)-200)/4;
gamen.style.backgroundImage='linear-gradient(90deg,#88ff88 '+a+'%,#000000 '+a+'%)';
}
</script>

 

 

コード解説

まずスクリプト内1行目。

document.addEventListener('scroll',fscr,false);

 

document(ページ)そのものに対してイベントリスナーを設定しています。

イベントの種類は'scroll'(スクロール)。

ページスクロールが行われるたびに、fscrという関数を呼び出します。

 

a=100-(Math.min(Math.max(gamen.getBoundingClientRect().top,200),600)-200)/4;

gamen、という任意のIDを持つ要素の「画面上の縦位置」を取得し、0~100の間の数値に変換しています。

ちょっとややこしい計算式になっていますが…。

gamen.getBoundingClientRect().top

が、その「画面上の縦位置」となります。

Math.max(gamen.getBoundingClientRect().top,200)

によって、「画面上の縦位置、または200の、いずれか大きい方」を取得。

Math.min(Math.max(gamen.getBoundingClientRect().top,200),600)

によって、「上記値、または600の、いずれか小さい方を取得するようにしています。

この時点で、画面のスクロール位置に応じて「200~600」の数値が取り出されます。

その値から200を引いて「0~400」に、そしてそれを4で割って「0~100」に。

最後にそれを「100から引く」事で「100~0」の数値が、変数aに代入されます。

(画面上の縦位置が200~600の時にその範囲内での位置に応じてaが変化する、という事になります。)

 

gamen.style.backgroundImage='linear-gradient(90deg,#88ff88 '+a+'%,#000000 '+a+'%)';

そうして算出した変数aを用いて、gamenというidを持つ要素の「background-image」プロパティの値に設定するlinear-gradientを構築します。

この式を実行すると、例えば変数aの値が「46」だった場合には、

#gamen{
background-image:linear-gradient(90deg,#88ff88 46%,#000000 46%);
}

CSSで指定したのと同じ、って事になります。

 

これが「スクロールイベントが発生するたび」に上書きされるので、サンプルのように「スクロールに応じて黄緑のバーが伸びていく」ような演出になるんですね。

 

 

あとがき

今回は単純にbackground-imageの内容を変化させる、というサンプルでしたが、JavaScriptからCSS指定を書き換えられる内容であれば、他にも様々な使い方が考えられます。

スクロールに応じて、スプラッシュイメージが透過していくものや、横からせり出してくるようなものなど、Webサイトでよく見かける演出が実現できますね^^

 

途中ややこしい計算式をはさみましたが、肝心な部分は

document.addEventListener('scroll',関数名,false);

によるイベントの監視と、

対象要素ID.getBoundingClientRect().top

による「画面上の縦位置」の取得の2点となります。

 

 

 

ってなとこで、今回はこのへんで!

次回もまた、よろしくお願いします^^