読みものJournal
- Date :
- Category :
- Share :

こんにちは、エンジニアの六川です。
2026年になりました。新たな年の幕開けですね!
私は寒がりなので冬があまり得意ではないのですが、今年は職場の皆さんから、誕生日プレゼントとしてマフラーをいただいたので、あたたかい冬が過ごせそうです。
さて今回は、数字をカウントアップさせるアニメーションの作り方をご紹介したいと思います。
カウントアップアニメーションを使うと、任意の値を動的に表現できるので、サイトのアクセントとしても効果的です。
参考:HANARIA(https://hanaria.jp/)
本記事では、JavaScriptライブラリの一種GSAPを用いて「特定の位置に到達したら、任意の値をカウントアップさせる」という仕組みを実装していきます。
私なりに噛み砕いて解説しているので、よろしければ最後までご覧ください。
( Index )
コードの全体図
まずはコードの全体図を確認しましょう。
HTML
<section data-countup-trigger>
<h1>Year</h1>
<p data-countup-target data-from="0" data-to="2026">0</p>
</section>JavaScript
const countUpTrigger = document.querySelector('[data-countup-trigger]');
const countUpTargets = document.querySelectorAll('[data-countup-target]');
countUpTargets.forEach( target =>{
const countElement = {
from: target.dataset.from,
to: target.dataset.to
}
const numberElement = {
count: countElement.from
}
gsap.to(numberElement, {
count: countElement.to,
duration: 2,
ease: "power4.out",
scrollTrigger: {
markers: true,
trigger: countUpTrigger,
start: 'top center',
},
onUpdate:()=>{
target.textContent = Math.floor(numberElement.count) ;
}
})
})コードの解説
大まかな流れは下記のとおりです。順を追って説明していきます。
- HTMLにdata属性で開始値、終了値を指定する
- data属性をJavaScriptで取得する
- GSAPを使って、取得した値を1つずつ繰り上げる
HTMLにdata属性で開始値、終了値を指定する
まずは、どの値からどの値までカウントアップさせるかをHTML側で指定します。
今回はdata属性を使って、data-toに開始値、data-fromに終了値を指定しました。data属性を使うことで、その値をJavaScriptで取得することができます。
<section data-countup-trigger>
<h1>Year</h1>
<p data-countup-target data-from="0" data-to="2026">0</p>
</section>data属性をJavaScriptで取得する
次に、HTMLで設定したdata属性の値を取得してみましょう。data属性はdatasetプロパティを使うことで取得できます。
下記のように、属性名の data-より後の部分を使用して取得します。
const countUpTargets = document.querySelectorAll('[data-countup-target]');
console.log(countUpTargets.dataset.from); // 0
console.log(countUpTargets.dataset.to); // 2026それぞれの値が取得できましたね。
GSAPを使って、取得した値を1つずつ繰り上げる
次はいよいよGSAPの出番です。
今回はスクロールをトリガーとして、可視領域に入ったらカウントアップを発動させたいと思います。
まずは、要素の数だけアニメーションを動作させたいので、forEach を使ってトリガーの数だけループさせます。
2のデータ属性で取得した値も、扱いやすいようにオブジェクトとして格納しておきましょう。
const countUpTargets = document.querySelectorAll('[data-countup-target]');
countUpTargets.forEach( target =>{
const countElement = {
from: target.dataset.from,
to: target.dataset.to
}
})続いて、gsap.to() を使って、具体的な動きを指定しましょう。
GSAPでは、第1引数には対象とする要素、第2引数にはプロパティと値を指定します。
今回の場合、data属性で指定した開始値から終了値までをカウントさせたいので、第1引数にnumberElement、第2引数にcountプロパティを指定します。
countUpTriggerをトリガーとして、要素の上部が画面の中央に来たら一斉にアニメーションが開始されます。
const numberElement = {
count: countElement.from
} ;
gsap.to(numberElement, { // アニメーションさせたい要素(numberElement)
count: countElement.to, // 終了値
duration: 2, // アニメーションの時間(秒)
ease: "power4.out", // イージングの種類
scrollTrigger: {
trigger: countUpTrigger, // トリガーとなる要素
start: 'top center', // トリガーの開始位置
}
})最後に、コールバックを指定します。onUpdateは、アニメーション中に数字が更新されるたび(1秒間に約60回)に実行される関数です。GSAPは裏側で変数の値を書き換えるだけなので、そのままでは画面上の表示は変わりません。
そのため、onUpdateを使って、更新された最新の数字を target.textContent にその都度上書きしてあげる必要があります。
また、GSAPは滑らかに動かすために小数の状態で計算を進めます。そのまま表示すると「1.2345…」のように表示されてしまうため、Math.floor(または Math.trunc)を使って整数に整えてから画面に出しましょう。
onUpdate:()=>{
countUpTarget.textContent = Math.floor(numberElement.count);
}Math.floorとは
例えば、Math.floor(2.7)は2を返します。
ちなみに、最後のonUpdateにて toLocaleString()を追加することで、数字をカンマ区切りにすることもできます。
countUpTarget.textContent = Math.floor(numberElement.count).toLocaleString() ; // 2,026完成!
完成したアニメーションはこちら。
おわりに
いかがでしたか。GSAPを用いることで、スクロール位置に応じたアニメーションを簡単に実装することができます。
ぜひ皆さんのサイトでも取り入れてみてくださいね。
