feat: add emoji to pot animation

This commit is contained in:
YunYouJun
2022-04-17 03:27:55 +08:00
parent 7163fd350b
commit bbd9f840b5
5 changed files with 86 additions and 21 deletions

1
src/components.d.ts vendored
View File

@@ -5,6 +5,7 @@ import '@vue/runtime-core'
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AnimateStuff: typeof import('./components/AnimateStuff.vue')['default']
BaseFooter: typeof import('./components/BaseFooter.vue')['default']
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
Counter: typeof import('./components/Counter.vue')['default']

View File

@@ -0,0 +1,18 @@
<template>
<span class="animate-stuff" w="4" h="4">
<slot />
</span>
</template>
<style>
.animate-stuff {
visibility: hidden;
position: absolute;
z-index: 10;
top: 0;
left: 0;
border-radius: 50%;
background: #02b6fd;
transition: left .6s linear, top .6s cubic-bezier(0.5, -0.5, 1, 1);
}
</style>

View File

@@ -1,5 +1,6 @@
<script lang="ts" setup>
import { useGtm } from '@gtm-support/vue-gtm'
import AnimateStuff from './AnimateStuff.vue'
import type { StuffItem } from '~/data/food'
import { meat, staple, tools, vegetable } from '~/data/food'
import recipeData from '~/data/recipe.json'
@@ -32,17 +33,52 @@ const displayedRecipe = computed(() => {
})
})
const { x, y } = usePointer()
const animateStuff = ref()
const recipeBtn = ref<HTMLButtonElement>()
const { top, left } = useElementBounding(recipeBtn)
const playAnimation = () => {
if (animateStuff.value) {
const el = animateStuff.value.$el
el.style.visibility = 'visible'
el.style.top = `${y.value}px`
el.style.left = `${x.value}px`
el.style.transition = 'none'
setTimeout(() => {
el.style.visibility = 'visible'
el.style.top = `${top.value}px`
el.style.left = `${left.value}px`
el.style.transition = 'left .4s linear, top .4s cubic-bezier(0.5, -0.5, 1, 1)'
}, 0)
el.ontransitionend = () => {
el.style.visibility = 'hidden'
}
}
}
const gtm = useGtm()
const toggleStuff = (item: StuffItem, category = '') => {
const curEmoji = ref('')
const toggleStuff = (item: StuffItem, category = '', e?: Event) => {
rStore.toggleStuff(item.name)
if (curStuff.value.includes(item.name)) {
playAnimation()
curEmoji.value = item.emoji
}
gtm?.trackEvent({
event: 'click',
category: `${category}_${item.name}`,
action: 'click_stuff',
label: '食材',
})
rStore.toggleStuff(item.name)
}
/**
@@ -53,6 +89,11 @@ const clickTool = (item: StuffItem) => {
const value = item.name
rStore.toggleTools(value)
if (curTools.value.includes(value)) {
playAnimation()
curEmoji.value = item.emoji
}
gtm?.trackEvent({
event: 'click',
category: `tool_${value}`,
@@ -66,16 +107,26 @@ const { isVisible, show } = useInvisibleElement(recipePanel)
</script>
<template>
<Transition>
<AnimateStuff ref="animateStuff">
{{ curEmoji }}
</AnimateStuff>
</Transition>
<Transition>
<button
v-if="displayedRecipe.length !== recipe.length && displayedRecipe.length && !isVisible"
class="fixed inline-flex justify-center items-center rounded rounded-full shadow hover:shadow-md"
v-if="displayedRecipe.length !== recipe.length && isVisible"
ref="recipeBtn"
class="cursor-pointer fixed inline-flex justify-center items-center rounded rounded-full shadow hover:shadow-md"
bg="green-50" w="10" h="10" bottom="4" right="4"
text="green-600"
@click="show"
>
<!-- <div i-mdi-bowl-mix-outline /> -->
🍲
<span v-if="displayedRecipe.length">
<div i-mdi-bowl-mix-outline />
</span>
<span v-else>
<div i-mdi-bowl-outline />
</span>
</button>
</Transition>
@@ -89,7 +140,7 @@ const { isVisible, show } = useInvisibleElement(recipePanel)
<VegetableTag
v-for="item, i in vegetable" :key="i"
:active="curStuff.includes(item.name)"
@click="toggleStuff(item, 'vegetable')"
@click="() => toggleStuff(item, 'vegetable')"
>
<span v-if="item.emoji" class="inline-flex">{{ item.emoji }}</span>
<span v-else-if="item.image" class="inline-flex">
@@ -177,11 +228,6 @@ const { isVisible, show } = useInvisibleElement(recipePanel)
大胆尝试一下或者<a href="#" @click="rStore.reset()">
<strong>换个组合</strong></a>
</span>
<br>
<a m="t-4" border="b-1 dashed" class="inline-flex text-sm text-blue-600 dark:text-blue-400" href="https://docs.qq.com/sheet/DZUpJS0tQZm1YYWlt?referrer=1&tab=mwn1v5" target="_blank">
更多囤货水培攻略隔离食用手册大全
</a>
</div>
</Transition>
</div>

View File

@@ -1,6 +1,5 @@
import { useElementBounding, useIntersectionObserver } from '@vueuse/core'
import { useElementBounding } from '@vueuse/core'
import type { Ref } from 'vue'
import { ref } from 'vue'
/**
* trigger show invisible element
@@ -8,15 +7,13 @@ import { ref } from 'vue'
* @returns
*/
export function useInvisibleElement(target: Ref<HTMLElement>) {
const isVisible = ref(false)
const { top } = useElementBounding(target)
useIntersectionObserver(target, ([{ isIntersecting }]) => {
isVisible.value = isIntersecting
const isVisible = computed(() => {
return window.scrollY < top.value
})
const show = () => {
// scroll when collapse is not visible
if (!isVisible.value)
window.scrollTo(0, top.value)
}

View File

@@ -19,6 +19,9 @@ const rStore = useRecipeStore()
</p>
<p>
<ChooseFood />
<a m="t-2" border="b-1 dashed" class="inline-flex text-sm text-blue-600 dark:text-blue-400" href="https://docs.qq.com/sheet/DZUpJS0tQZm1YYWlt?referrer=1&tab=mwn1v5" target="_blank">
更多囤货水培攻略隔离食用手册大全
</a>
</p>
</div>
</template>