最近では見かけることが少なくなったタイプライターアニメーション。
私も、まだ現役でjQueryを使用していた時に実装経験があり、割と面倒だった覚えがあります。
ですが、以前に比べasync
await
が出てきたことにより、実装しやすくなっている気がします。
ということで、早速Vue2でタイプライターアニメーションを作成してみましょう。
# この記事で解決すること
- 当サイトのTOPページのローディングアニメーションにあるようなタイプライターが実装できる
※タイプライターのみです
前提
表題にもある通り、今回はVue2で実装します。
ですが、重要なのはどのようなmethods
を組むかという点にあるので、Vue3への流用もある程度できるのではないかと思います。
また、コンポーネント化したいのでSFC構文で作成します。
- Vueを実装できる環境
- Vue Templateをコンパイル・トランスパイルできる環境
フォルダ構成
- folder
- src
- js
- app.js
- components
- typelighter.vue
- js
- index.html
- src
手順
- Vue Templateの初期設定
- methodsの処理
- 乱数の取得
- 文字出力アニメーションの設定
- アニメーションループの作成
- 実装
- mountedに実装
- componentの読み込み
- templateの挿入
- 実働確認
Vue Templateの初期設定
今回はSFC構文ですので、htmlとcssもtemplate内に入れ込みます。
typelighter.vue
<template>
<div class="typelighter-text" v-text="returnText + randText"></div>
</template>
<style>
.typelighter-text {
font-family: sans-serif;
font-weight: bold;
letter-spacing: .3rem;
}
</style>
<script>
export default {
props: {
text: {
type: String,
default: 'Hello World',
require: true
},
},
data() {
return {
returnText: '',
randText: ''
}
},
methods: {
},
}
</script>
props | |
---|---|
text |
htmlに挿入するカスタムブロックでテキストを設定したいので、 propsには text を設定しておきます。default: ‘Hello World’(必須ではない) require: true |
data | |
returnText |
props:text の文字を1文字づつ入れるために設定 |
randText |
文字が表示されるまでの間にランダムで表示される文字を入れるために設定 |
# point
returnText
とrandText
に分けている理由は「実際に表示したい文字」と「その文字が表示されるまでの間にランダムで表示される文字」を分けておきたかったからです。
例えば「あいう」という文字をタイプライター形式で表示する場合
「$」→「あ$」→「あい$」→「あいう」(「$」はランダムな文字と仮定する)
にするためです。
methodsの処理
乱数の取得
ランダムな文字を表示したい場合、表示前の段階でランダムな文字を生成する必要があります。
typelighter.vue: methods
getRandom() {
// 表示されるランダムな文字の設定(47文字:何文字でもOK)
let randStr = "abcdefghijklmnopqrstuvwxyz0123456789<>$&!'()%[]"
// ランダムな文字を配列に変換
let randAry = [...randStr]
// 0~46(47-1)の中でランダムな数字を計算(x番目と仮定する)
let randNum = Math.floor(Math.random() * (randAry.length - 1))
// randAryのx番目の文字をreturn
return randAry[randNum]
},
文字出力アニメーションの設定
ランダムな文字を規定回数出力し終わったらprops:text
の文字をreturn
するというmethodになります。
1文字づつこのmethodを繰り返す必要がありますので、最終でこのmethodをループさせることになります。
typelighter.vue: methods
// textには、ランダムな文字を規定回数出力し終わった時点で返る文字が入ります(次項で設定)
returnStr(text) {
// ループカウントをリセット
let cnt = 0
// 規定回数の設定
let cntMax = 3
// Promise
return new Promise((resolve) => {
// 25msでループ(一番違和感がなかった)
setInterval(() => {
// ループカウントが規定回数に達しているかの判定
if (cnt == cntMax) {
// 規定回数に達していた場合は text を返す
resolve(text)
} else {
// 規定回数に達していない場合は ランダムな文字を出力してループカウントを++
this.randText = this.getRandom()
cnt ++
}
}, 25)
})
},
props:text
を1文字づつ処理しますので、1文字終わったら次の文字にいかないといけません。
そのためには、秒数で管理するか、async
await
を使用するかの実質2択になってきます。(watchでも頑張ったらできそうですが…)
11, 20行目
次項で使用するasync
await
のために、処理が終わったらtext
をPromise Object
として返す設定にしています。
8, 28行目
この行でアニメーションの速度などを制御しています。
25msを3回ループするので、1文字75msで終わることになります。
アニメーションループの作成
では、先程作成したアニメーションをループします。
typelighter.vue: methods
async printText() {
// props:text の文字数分だけループさせる
// text='test'の場合、['t', 'e', 's', 't'] がループで回る
for await (let text of [...this.text]) {
// returnStrが終わったらreturnTextにtextが入る
this.returnText += await this.returnStr(text)
}
// すべての文字を出力し終わったらランダムな文字は必要ないのでバイバイ
this.randText = ''
},
async
await
が出てきてから、アニメーションとかでよく使う、「○○が終わるまで〇〇の処理は待ってね」っていうのが本当に楽になりましたね。
ということで、methodsの処理は完了となります。
実装
mountedに実装
mountedにthis.printText()
を書いて.Vueファイルの処理は完了です。
typelighter.vue: mounted
mounted() {
this.printText()
},
componentの読み込み
htmlに挿入するには、jsファイル内でcomponentを使用することを書かなくてはいけません。
Vue2ではこんな感じです。
app.js
import typelighter from './components/typelighter.vue'
new Vue({
el: '#typelighter',
components: { typelighter },
})
templateの挿入
問題なくcomponentが読み込めていれば、あとはhtmlに挿入するだけです。
index.html
<div id="typelighter">
<typelighter text="Hello World" />
</div>
実働確認
実際に動かすとこんな感じです。
See the Pen
Untitled by [ brandnew] (@brandnew-work)
on CodePen.
最後に
いかがでしたでしょうか。
async
await
を使えば、たった3methodsでタイプライターが実装できることがわかりましたね!
当サイトのTOPのローダーのようにするには、上記にプラスしてcssアニメーションとasync
await
で実装できますので、みなさんも試してみてください。
それよりも「Highlighting Code Block」に「Vue Template」のシンタックスなくて2記事目にしてコードハイライターのプラグイン変えてやろうかと思いました。。。
それでは皆様よいVueライフを!