Vue.js 数値の変化をドラムロールアニメーションする
Vue.js
の公式ドキュメントの状態のトランジションで紹介されている数値のドラムロールアニメーションをコンポーネントとして実装します。
公式のサンプルではTween.js
を使用していますが、今回は外部ライブラリを使用せずに作成します。
AnimatedNumber.vue
<template>
<span>{{ animated_number }}</span>
</template>
<style scoped>
/*必要に応じて追加*/
</style>
<script>
export default {
props: {
value: {
type: Number,
required: true
}
},
data () {
return {
animated_number: 0
};
},
watch: {
value (newValue, oldValue) {
let timeCnt = 0;
let timer;
const animate = () => {
timeCnt++;
if (timeCnt <= 60) {
this.animated_number = Math.floor((newValue - oldValue) * timeCnt / 60) + oldValue;
timer = setTimeout(() => {
animate();
}, 10);
} else {
clearTimeout(timer);
timer = null;
this.animated_number = newValue;
}
};
animate();
}
},
mounted () {
this.animated_number = this.value;
}
};
</script>
使用方法
<template>
<div>
<input v-model.number="num" type="number">
<AnimatedNumber :value="num"></AnimatedNumber>
</div>
</template>
<style scoped>
</style>
<script>
import AnimatedNumber from './AnimatedNumber.vue';
export default {
components: { AnimatedNumber },
data () {
return {
num: 0,
};
}
};
</script>
解説
props
で親から渡された値(value
)をwatch
で監視します。
value
が変更されるたびにwatch
処理でanimated_number
を徐々に変化させます。
value
ではなくanimated_number
をtemplate
で表示するようにすれば、徐々に変化する様子(アニメーション)が表示されるようになります。
ドラムロール
Tween.js
を使わずにドラムロール処理を実装しました。
1〜10に変化する時と、1〜1000に変化するときでアニメーションの長さが変わらないように、1ステップあたりの数値の変化量を工夫しています。
watch
の処理ではアローファンクションを使っているのでthis
のスコープには注意が必要です。