カンマ

Web

Nuxt3とGSAP ScrollTriggerでカンマ含み数字をカウントアニメーションさせる

北海道の事件というアプリを作っている中で、画面に到達したら事件数をカウントアニメーションさせていたが、自作のカンマ区切りプラグインだと、数字が切り上げられ、一桁になることが発覚。どうしたものかと、調べたので、メモ。

カンマ区切りの数字の挙動がおかしい

昨年末から北海道で発生した事件を表示するアプリを作っていて、月ごとと総数で事件数を表示していました。せっかくだから、アニメーションさせるかとやってみると、カンマがない時は普通にカウントされるのですが、千の位以上でカンマがあると、数字が一つしか表示されません。自作プラグインだと、GSAPとうまく連携できないみたい。他にやり方がないかなとググってみると、下記のいい感じのページがあり、さっそく取り入れることに。

Counting numbers with separator (thousands)
Hey there, I am animating several figures on a website. Now …

TS仕様に変更する

上記を自分のプログラムにコピペして使ってみると、とりあえずちゃんと動くことはわかりました。ただし、vue-tscエラーが結構発生しているので、修正しなければなりません。copilotに聞きながら、エラーに合わせて変更すると、なんだかおかしなエラーが出てきたので、一旦リセット。変更しておかしくなるものはそのまま残して、辻褄をあわせる形で変更すると、vue-tscエラーが解消された上で、動きました。ただ、もっとうまくいくやり方があるような気がします。一応、できたものは以下。composablesにファイルがあり、それを使用する場所で呼び出して、animate(‘.lastmonthNumber’, ‘.lastmonthNumberBox’);のようにクラスを引数に渡し、使います。nextTickが入っているのは、別の場所でawaitで数字を取得しているので、その遅延処理のためです。

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);

export function useAnimation () {
  function numberWithCommas (n: string) {
    const parts = n.toString().split('.');
    return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  }

  function animate (targetSelector: string, targetSelectorBox: string) {
    nextTick(() => {
      gsap.from(targetSelector, {
        textContent: 0,
        duration: 3,
        ease: 'Power4.easeOut',
        snap: { textContent: 1 },
        stagger: {
          each: 1,
          onUpdate: function (this: gsap.core.Tween) {
            this.targets().forEach((target: unknown) => {
              const element = target as HTMLElement;
              const val = gsap.getProperty(element, 'innerText');
              element.innerText = numberWithCommas(String(val));
            });
          }
        },
        roundProps: 'innerText',
        scrollTrigger: {
          trigger: targetSelectorBox,
          start: 'center bottom-=20',
          end: 'bottom+=1000 top',
          markers: false
        }
      });
    });
  }

  return { animate };
}

これにより、数字のカウントアニメーションは解決したんですが、apexchartsの方のアニメーションがうまくいってないんですよね。scrolltriggerとの組み合わせで、いけそうな気がするんだけどなぁ。

コメント