🎯 概要
「OS Yamato」では、メッセージで特定の言葉を入力すると、桜が舞ったり、星が流れたり、紙吹雪が舞ったりといった演出(エフェクト)が即時発生します。日本らしい侘び寂びを演出したいのです。
本記事ではその 演出構造の中核である以下の3つの要素を解説します:
1. useChatEffects.ts(キーワードマッチングとトリガー)
2. ChatEffect.vue(アニメーションの表示ロジック)
3. ChatView.vue(チャット本文での統合)
デモ動画
① useChatEffects.ts の構造:言葉 → アニメーション変換
export function useChatEffects(chatEffect: Ref<any>, messageAnimationEnabled: Ref<boolean>) {
const specialPatterns = [
{ pattern: /(愛してる|i love you)/i, effect: 'moon' },
{ pattern: /(星空|starry sky)/i, effect: 'starry' },
{ pattern: /(おめでとう|congrats)/i, effect: 'confetti' },
{ pattern: /(夏|summer)/i, effect: 'summer' }
// さらに多数あり
]
function maybePlayEffect(content: string): boolean {
for (const { pattern, effect } of specialPatterns) {
if (pattern.test(content)) {
chatEffect.value.playEffect(effect)
return true
}
}
return false
}
return { maybePlayEffect }
}
✅ 特徴:
• RegExp による自然言語パターン抽出
• 日本語・英語・中国語・スペイン語など多言語対応
• chatEffect.value.playEffect(effectName) を呼び出すだけ
② ChatEffect.vue: トリガーされたエフェクトの描画
<Teleport to="body">
<div v-if="effectType === 'rain'" class="effect-container">
<div v-for="n in 50" :key="n" class="raindrop" :style="randomRainStyle()" />
</div>
<div v-if="effectType === 'starry'" class="effect-container">
<div v-for="n in 50" :key="n" class="star" :style="randomStarStyle()" />
<div v-for="n in meteorCount" :key="'m-' + n" class="meteor" :style="randomMeteorStyle()" />
</div>
<div v-if="effectType === 'confetti'" class="effect-container">
<div v-for="n in 100" :key="n" class="confetti" :style="randomConfettiStyle(n)" />
</div>
<!-- 他にも 'moon', 'bubble', 'autumn', 'mishima' など全14種 -->
</Teleport>
✅ 特徴:
• effectType に応じて動的にエフェクトを描画
• randomXxxStyle() によってアニメーションを毎回変化させる
• triggerXxx() を通じてアニメーションの長さや画像を制御
③ ChatView.vue との統合
watch(messages, () => {
const last = messages.value.at(-1)
if (last && messageAnimationEnabled.value) {
maybePlayEffect(last.content)
}
})
✅ 特徴:
• 新しいチャットメッセージを検知して maybePlayEffect() を実行
• エフェクトが発動されると、ChatEffect.vue 側で演出が描画
• ローカル環境で完結し、ユーザー設定で ON/OFF も可能
📎 まとめ
Vue + Composition API + GraphQL で 言葉と連動するUI演出 を実現
汎用的なパターンマッチングにより、柔軟かつ多言語で動作
実装は「設定+1行呼び出し」で統合可能なモジュール構成
⸻
🔗 関連リンク
GitHub: https://github.com/osyamato/os-yamato
Try it: https://hanaco875.com