Skip to content

Commit

Permalink
feat: add confetti animation
Browse files Browse the repository at this point in the history
  • Loading branch information
yb6b committed Mar 18, 2024
1 parent 5083f68 commit e2ce625
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 40 deletions.
132 changes: 93 additions & 39 deletions components/train/Train.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script setup lang="ts">
import { shallowRef, watch, onMounted, inject } from "vue";
import { shallowRef, watch, onMounted, inject, nextTick } from "vue";
import { Schedule } from "./schedule";
import { Card } from "./share";
import { useLocalStorage } from "@vueuse/core";
import confetti from "canvas-confetti";
const p = defineProps<{
/** 复习卡片的数据 */
Expand Down Expand Up @@ -55,61 +57,113 @@ function checkNextItem(answer: string) {
progress.value = thisSchedule.progress
}
const showConfetti = shallowRef(false)
watch(progress, (newV, oldV) => {
if (newV === p.cards.length && newV > oldV)
showConfetti.value = true
})
watch(showConfetti, async (v) => {
if (!v) return;
await nextTick();
var duration = 5000;
var animationEnd = Date.now() + duration;
var defaults = {
startVelocity: 30,
spread: 360,
ticks: 60,
zIndex: 0,
particleCount: 30,
shapes: [
confetti.shapeFromText({ text: '', scalar: 7 }),
confetti.shapeFromText({ text: '', scalar: 8 }),
confetti.shapeFromText({ text: '😆', scalar: 4 }),
confetti.shapeFromText({ text: '🎉', scalar: 5 }),
confetti.shapeFromText({ text: '👍', scalar: 5 }),
],
scalar: 2,
};
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
var interval = setInterval(function () {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
var particleCount = 50 * (timeLeft / duration);
// since particles fall down, start a bit higher than random
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
confetti({
...defaults, shapes: ['circle'],
particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 }
});
}, 250);
})
</script>

<template>
{{card}}
<div
:class="['md:w-2/3 w-full shadow-sm my-12 pb-24 bg-opacity-10 rounded-md', { 'bg-red-700': !isCorrect, 'bg-slate-500': isCorrect }]">
<div class="flex justify-center mb-24">
<progress class="progress w-full" :value="progress" :max="cards.length" />
</div>
<div class="flex justify-around mb-8">

<div class="w-40 flex justify-center h-28 p-5 overflow-hidden">
<Transition enterActiveClass="animate__animated animate__bounceInLeft"
leaveActiveClass="animate__animated animate__bounceOutRight"
mode="out-in">
<div :key="card.name"
:class="['text-6xl animate__animated', 'kaiti-font', fontClass, { 'text-red-400': !isCorrect, 'animate__headShake': !isCorrect }]">
{{ card.name }}</div>
</Transition>
</div>

<template v-if="!showConfetti">
<div class="flex justify-around mb-8">

<div class="w-40 flex justify-center h-28 p-5 overflow-hidden">
<Transition enterActiveClass="animate__animated animate__bounceInLeft"
leaveActiveClass="animate__animated animate__bounceOutRight" mode="out-in">
<div :key="card.name"
:class="['text-6xl animate__animated', 'kaiti-font', fontClass, { 'text-red-400': !isCorrect, 'animate__headShake': !isCorrect }]">
{{ card.name }}</div>
</Transition>
</div>

<!-- <Transition :key="card.name" :name="isCorrect ? 'right' : 'left'">
</Transition> -->
<div class="flex flex-col" v-if="'rel' in card || 'kind' in card">

<div class="flex flex-col" v-if="'rel' in card || 'kind' in card">
<div class="flex tracking-widest flex-col opacity-70" v-if="'rel' in card">

<div class="flex tracking-widest flex-col opacity-70" v-if="'rel' in card">
<div class="text-gray-500 text-sm">
相关的字:
</div>

<div class="text-gray-500 text-sm">
相关的字:
<div>
{{ card.rel }}
</div>
</div>

<div>
{{ card.rel }}
<div class=" tracking-widest pt-6 text-blue-600 dark:text-blue-300"
v-if="'kind' in card && card.kind == 'b'">
五个基础笔画
</div>
<div class=" tracking-widest pt-6 text-blue-600 dark:text-blue-300"
v-if="'kind' in card && card.kind == 'eb'">
25个二笔小码
</div>
</div>

<div class=" tracking-widest pt-6 text-blue-600 dark:text-blue-300"
v-if="'kind' in card && card.kind == 'b'">
五个基础笔画
</div>
<div class=" tracking-widest pt-6 text-blue-600 dark:text-blue-300"
v-if="'kind' in card && card.kind == 'eb'">
25个二笔小码
</div>
</div>
</div>
<div class="flex justify-center p-5">
<input id="input_el" type="text" placeholder="输入字根编码" v-model="userKeys"
:class="['input w-half max-w-xs input-bordered text-center input-sm dark:bg-slate-800 bg-white', { 'input-error': !isCorrect }]" />
</div>
<div :class="['text-center', { 'opacity-0': !isFirstLearn }]">答案是 <b class="font-mono">{{ card.key }}</b>
<span :class="[fontClass]" v-if="'comp' in card">({{ card.comp }})</span>
</div>
<div class="flex justify-center p-5">
<input id="input_el" type="text" placeholder="输入字根编码" v-model="userKeys"
:class="['input w-half max-w-xs input-bordered text-center input-sm dark:bg-slate-800 bg-white', { 'input-error': !isCorrect }]" />
</div>
<div :class="['text-center', { 'opacity-0': !isFirstLearn }]">答案是 <b class="font-mono">{{ card.key }}</b>
<span :class="[fontClass]" v-if="'comp' in card">({{ card.comp }})</span>
</div>
</template>
<template v-else>
<div class="p-10 text-6xl text-center font-bold text-orange-800 font-sans tracking-widest -rotate-6">
🎉恭喜完成练习!!</div>
<div class="flex justify-center mt-10">
<button class="btn btn-success" @click="_ => showConfetti = false">继续练习</button>
</div>
</template>

</div>

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"preview": "vitepress preview src "
},
"dependencies": {
"@vueuse/core": "^10.9.0"
"@vueuse/core": "^10.9.0",
"canvas-confetti": "^1.9.2"
}
}
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e2ce625

Please sign in to comment.