feat: 添加多种动画效果,包括触摸反馈、涟漪、弹性缩放和滑入动画,优化用户交互体验

This commit is contained in:
2026-01-03 17:27:30 +07:00
parent bea34a3e22
commit 1c931c40b3
2 changed files with 125 additions and 8 deletions

View File

@@ -121,3 +121,117 @@
.animate-rotate-glow { .animate-rotate-glow {
animation: rotate-glow 10s linear infinite; animation: rotate-glow 10s linear infinite;
} }
/* 移动端触摸反馈动画 */
@keyframes tap-feedback {
0% {
transform: scale(1);
}
50% {
transform: scale(0.95);
}
100% {
transform: scale(1);
}
}
.animate-tap {
animation: tap-feedback 0.2s ease-out;
}
/* 涟漪效果 */
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(4);
opacity: 0;
}
}
.animate-ripple {
animation: ripple 0.6s ease-out;
}
/* 弹性缩放动画 */
@keyframes bounce-scale {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
.animate-bounce-scale {
animation: bounce-scale 0.3s ease-out;
}
/* 滑入动画 - 从左 */
@keyframes slide-in-left {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.animate-slide-in-left {
animation: slide-in-left 0.4s ease-out forwards;
opacity: 0;
}
/* 滑入动画 - 从右 */
@keyframes slide-in-right {
from {
opacity: 0;
transform: translateX(30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.animate-slide-in-right {
animation: slide-in-right 0.4s ease-out forwards;
opacity: 0;
}
/* 脉冲缩放动画 */
@keyframes pulse-scale {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.02);
}
}
.animate-pulse-scale {
animation: pulse-scale 2s ease-in-out infinite;
}
/* 隐藏滚动条 */
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
/* 平滑滚动 */
.smooth-scroll {
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
}

View File

@@ -116,12 +116,14 @@ useHead({
:label="locale === 'zh-CN' ? 'EN' : '中文'" :label="locale === 'zh-CN' ? 'EN' : '中文'"
color="neutral" color="neutral"
variant="ghost" variant="ghost"
class="transition-all duration-300 active:scale-90 touch-manipulation"
@click="toggleLanguage" @click="toggleLanguage"
/> />
<UButton <UButton
:icon="isDark ? 'i-heroicons-sun' : 'i-heroicons-moon'" :icon="isDark ? 'i-heroicons-sun' : 'i-heroicons-moon'"
color="neutral" color="neutral"
variant="ghost" variant="ghost"
class="transition-all duration-300 active:scale-90 active:rotate-180 touch-manipulation"
@click="colorMode.preference = isDark ? 'light' : 'dark'" @click="colorMode.preference = isDark ? 'light' : 'dark'"
/> />
</div> </div>
@@ -146,13 +148,14 @@ useHead({
</div> </div>
<!-- Categories --> <!-- Categories -->
<div class="flex items-center gap-2 overflow-x-auto pb-2"> <div class="flex items-center gap-2 overflow-x-auto pb-2 scrollbar-hide">
<UButton <UButton
v-for="category in categories" v-for="category in categories"
:key="category.id" :key="category.id"
:label="category.name[locale as 'zh-CN' | 'en-US']" :label="category.name[locale as 'zh-CN' | 'en-US']"
:color="selectedCategory === category.id ? 'primary' : 'neutral'" :color="selectedCategory === category.id ? 'primary' : 'neutral'"
:variant="selectedCategory === category.id ? 'solid' : 'ghost'" :variant="selectedCategory === category.id ? 'solid' : 'ghost'"
class="transition-all duration-300 active:scale-90 touch-manipulation"
@click="selectedCategory = category.id" @click="selectedCategory = category.id"
/> />
</div> </div>
@@ -170,7 +173,7 @@ useHead({
<div class="absolute -inset-0.5 bg-gradient-to-r from-primary-500 via-purple-500 to-blue-500 rounded-2xl opacity-0 group-hover:opacity-100 blur transition-all duration-500 group-hover:blur-md"></div> <div class="absolute -inset-0.5 bg-gradient-to-r from-primary-500 via-purple-500 to-blue-500 rounded-2xl opacity-0 group-hover:opacity-100 blur transition-all duration-500 group-hover:blur-md"></div>
<UCard <UCard
class="cursor-pointer backdrop-blur-sm bg-white/90 dark:bg-gray-900/90 border border-gray-200/50 dark:border-gray-800/50 transition-all duration-500 hover:shadow-2xl hover:shadow-primary-500/20 hover:-translate-y-2 relative overflow-hidden" class="cursor-pointer backdrop-blur-sm bg-white/90 dark:bg-gray-900/90 border border-gray-200/50 dark:border-gray-800/50 transition-all duration-500 hover:shadow-2xl hover:shadow-primary-500/20 hover:-translate-y-2 active:scale-95 active:shadow-lg relative overflow-hidden touch-manipulation"
@click="openAppDetail(app)" @click="openAppDetail(app)"
> >
<!-- 内部发光效果 --> <!-- 内部发光效果 -->
@@ -178,9 +181,9 @@ useHead({
<div class="flex items-start gap-4 relative z-10"> <div class="flex items-start gap-4 relative z-10">
<!-- App Icon --> <!-- App Icon -->
<div class="size-16 rounded-2xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center text-white font-bold text-2xl shrink-0 shadow-lg shadow-blue-500/50 relative overflow-hidden group-hover:shadow-2xl group-hover:shadow-blue-500/60 transition-all duration-500 group-hover:scale-110 group-hover:rotate-3 p-2"> <div class="size-16 rounded-2xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center text-white font-bold text-2xl shrink-0 shadow-lg shadow-blue-500/50 relative overflow-hidden group-hover:shadow-2xl group-hover:shadow-blue-500/60 transition-all duration-500 group-hover:scale-110 group-hover:rotate-3 group-active:scale-105 group-active:rotate-1 p-2">
<div class="absolute inset-0 bg-gradient-to-tr from-white/0 via-white/30 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700"></div> <div class="absolute inset-0 bg-gradient-to-tr from-white/0 via-white/30 to-white/0 translate-x-[-100%] group-hover:translate-x-[100%] group-active:translate-x-[50%] transition-transform duration-700"></div>
<img :src="app.icon" :alt="app.name" class="size-full object-contain relative z-10 rounded-lg" /> <img :src="app.icon" :alt="app.name" class="size-full object-contain relative z-10 rounded-lg transition-transform duration-300 group-active:scale-95" />
</div> </div>
<!-- App Info --> <!-- App Info -->
@@ -207,7 +210,7 @@ useHead({
label="iOS" label="iOS"
size="sm" size="sm"
block block
class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1" class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1 active:scale-95 active:shadow-md touch-manipulation"
@click.stop="handleDownload(app, 'ios')" @click.stop="handleDownload(app, 'ios')"
/> />
<UButton <UButton
@@ -216,7 +219,7 @@ useHead({
label="Android" label="Android"
size="sm" size="sm"
block block
class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1" class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1 active:scale-95 active:shadow-md touch-manipulation"
@click.stop="handleDownload(app, 'android')" @click.stop="handleDownload(app, 'android')"
/> />
<UButton <UButton
@@ -225,7 +228,7 @@ useHead({
label="Web" label="Web"
size="sm" size="sm"
block block
class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1" class="transition-all duration-300 hover:shadow-lg hover:shadow-blue-500/50 hover:-translate-y-1 active:scale-95 active:shadow-md touch-manipulation"
@click.stop="handleDownload(app, 'h5')" @click.stop="handleDownload(app, 'h5')"
/> />
</div> </div>