OSU 打擊鈕 button
如同 OSU 遊戲的打擊鈕,看準時機點擊按鈕吧!(ゝ∀・)b
至於甚麼是 OSU 遊戲,可以來這裡看看。
技術關鍵字
| 名稱 | 描述 |
|---|---|
| Pointer 事件 | 偵測滑鼠或觸控點移動、點擊、懸停等等事件,取得座標、目標等等資訊 |
| JS 動畫 | 基於 JavaScript 實現的動畫,達成更複雜、精準的動畫控制,常見套件有 GSAP、anime.js 等 |
| Anime.js | 輕量級 JavaScript 動畫函式庫 |
使用範例
基本用法
觸碰後會出現接近圈圈,在圈圈大小與原本按鈕大小一致時,給他用力點下去!੭ ˙ᗜ˙ )੭
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-4 border border-gray-200 rounded-xl p-6">
<div class="flex justify-center">
<btn-osu-hit label="送出" />
</div>
</div>
</template>
<script setup lang="ts">
import BtnOsuHit from '../btn-osu-hit.vue'
</script>表單範例
Perfect 判定才會觸發事件,同時縮短反應時間,氣死你同事吧 ᕕ( ゚ ∀。)ᕗ
真的不訂飲料?( ・ิω・ิ) 貼心小提醒,您即將損失:
- 一杯好喝的飲料
- 悠閒的午休時光
- 美好的心情
操作已完成 (╥ω╥`)
查看範例原始碼
vue
<template>
<div class="relative flex flex-col gap-3 border border-red-300 rounded-lg bg-red-50 p-6">
<span class="text-xl text-red-800 font-bold">
真的不訂飲料?( ・ิω・ิ)
</span>
<span class="mt-2 text-red-700">
貼心小提醒,您即將損失:
</span>
<ul class="list-disc list-inside text-sm text-red-600 !m-0">
<li>一杯好喝的飲料</li>
<li>悠閒的午休時光</li>
<li>美好的心情</li>
</ul>
<div class="flex justify-end gap-4">
<base-btn label="取消" />
<btn-osu-hit
:reaction-time="400"
@perfect="handleClick"
>
<base-btn
label="確認"
class="text-white active:scale-95 !border-none !bg-red-600"
/>
</btn-osu-hit>
</div>
<div
class="pointer-events-none absolute inset-0 flex items-center justify-center bg-black/90 duration-500"
:class="done ? ' opacity-100' : 'opacity-0'"
>
<span class="text-2xl text-white font-bold">
操作已完成 (╥ω╥`)
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import BaseBtn from '../../base-btn.vue'
import BtnOsuHit from '../btn-osu-hit.vue'
const done = ref(false)
function handleClick() {
done.value = true
setTimeout(() => {
done.value = false
}, 2000)
}
</script>原理
使用了 Anime.js 來實作動畫並在點擊後依照縮放數值判斷打擊結果。
原始碼
API
Props
interface Props {
label?: string;
/** 反應時間,單位:毫秒 */
reactionTime?: number;
}Emits
interface Emits {
perfect: [];
great: [];
good: [];
miss: [];
}Methods
interface Expose {
/** 開始打擊,會出現 Approach Circle */
startBeat: () => void;
}Slots
interface Slots {
default?: () => unknown;
perfect?: () => unknown;
great?: () => unknown;
good?: () => unknown;
miss?: () => unknown;
}