diff --git a/src/app/globals.css b/src/app/globals.css index 36441b5db..1008d129f 100755 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -177,3 +177,17 @@ 0% { opacity: 0; transform: scale(0.92) translateY(8px); } 100% { opacity: 1; transform: scale(1) translateY(0); } } + +/* v0.11 晶体卡片 hover 扫描线 */ +@keyframes echo-scan { + 0% { top: 0%; opacity: 0; } + 20% { opacity: 1; } + 80% { opacity: 1; } + 100% { top: 100%; opacity: 0; } +} + +/* v0.11 晶体卡片 hover 边框流光 */ +@keyframes echo-border-flow { + 0% { background-position: 0% 50%; } + 100% { background-position: 200% 50%; } +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 409e8c690..53440c54e 100755 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -33,6 +33,7 @@ import { useGameLoop } from "@/hooks/useGameLoop"; import { useAudioSync } from "@/hooks/useAudio"; import { useGlobalTide } from "@/hooks/useGlobalTide"; import { useGameStore } from "@/store/gameStore"; +import { shallow } from "zustand/shallow"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { @@ -567,7 +568,32 @@ function CrystalYieldPanel() { } function StatsPanel() { - const s = useGameStore(); + // v0.11 性能优化:用 shallow 聚合 selector 替代全量订阅 useGameStore(), + // 避免每 tick(250ms)因无关字段变化触发重渲染。仅当所列字段引用变化才重渲染。 + const s = useGameStore( + (st) => ({ + totalDecoded: st.totalDecoded, + ascensions: st.ascensions, + blueprints: st.blueprints, + tech: st.tech, + fragments: st.fragments, + achievements: st.achievements, + constellation: st.constellation, + contact: st.contact, + crystalsPerSec: st.crystalsPerSec, + crystalCap: st.crystalCap, + insightMult: st.insightMult, + totalExpeditions: st.totalExpeditions, + bossKills: st.bossKills, + starTidesEncountered: st.starTidesEncountered, + chronicle: st.chronicle, + energy: st.energy, + energyMax: st.energyMax, + attributes: st.attributes, + pendingAttrPoints: st.pendingAttrPoints, + }), + shallow + ); const achCount = Object.values(s.achievements).filter(Boolean).length; // 深空信标本地排行榜最高分(独立 localStorage) const [beaconBest, setBeaconBest] = useState(null); diff --git a/src/components/game/DecodeArray.tsx b/src/components/game/DecodeArray.tsx index 5cf4be3ee..644858383 100755 --- a/src/components/game/DecodeArray.tsx +++ b/src/components/game/DecodeArray.tsx @@ -408,13 +408,33 @@ function CrystalCard({ return ( );