From a5b90e0cab695727c863e1e26433cac2a80d950b Mon Sep 17 00:00:00 2001
From: 2977094657 <2977094657@qq.com>
Date: Sun, 22 Feb 2026 22:18:58 +0800
Subject: [PATCH] =?UTF-8?q?improvement(wrapped-ui):=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E5=B8=B8=E7=94=A8=E8=AF=AD=E8=AF=8D=E4=BA=91=E5=8D=A1=E4=BA=A4?=
=?UTF-8?q?=E4=BA=92=E4=B8=8E=E8=A7=86=E8=A7=89=E8=A1=A8=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Card06 文案改为年度常用语,展示候选句数、独特短句数与 topKeyword。
- 移除隐私开关、跳过按钮和粒子爆炸层,简化动效流程与交互路径。
- 词云布局改为百分比坐标 + 自适应缩放,点击词后的例句面板改为 Teleport 固定定位。
- 优化空态文案与再看一遍入口,提升移动端可读性与操作一致性。
---
.../wrapped/cards/Card06KeywordsWordCloud.vue | 140 +-----
.../visualizations/KeywordWordCloud.vue | 401 +++++++++++-------
2 files changed, 257 insertions(+), 284 deletions(-)
diff --git a/frontend/components/wrapped/cards/Card06KeywordsWordCloud.vue b/frontend/components/wrapped/cards/Card06KeywordsWordCloud.vue
index 54b0988..99a637b 100644
--- a/frontend/components/wrapped/cards/Card06KeywordsWordCloud.vue
+++ b/frontend/components/wrapped/cards/Card06KeywordsWordCloud.vue
@@ -9,27 +9,13 @@
:style="{ zIndex: 9999 }"
@pointerdown="onStagePointerDown"
>
-
-
-
-
-
-
-
- 点击空白处加速 · 右上角可重播
+ 点击空白处加速
@@ -44,7 +30,6 @@
>
@@ -57,12 +42,6 @@
-
-
@@ -75,7 +54,11 @@
你的话,正在涌来。
- 每一句话都是一个气泡,最终爆开成你的年度关键词词云。点击关键词,回看它出现的瞬间。
+ 这一年,你一共发出了 {{ card.data?.meta?.matchedCandidates || 0 }} 句简短的表达,其中 {{ card.data?.meta?.uniquePhrases || 0 }} 句话成了你的专属口头禅。
+
+ 「{{ card.data.topKeyword.word }}」是你最常说的话,足足被你重复了 {{ card.data.topKeyword.count }} 次。
+
+ 点击气泡,找回当时的心情。
@@ -87,32 +70,22 @@
class="kw-stage relative w-full h-[56vh] min-h-[360px] max-h-[680px] rounded-[28px] overflow-hidden"
>
-
-
-
-
-
-
+
+
+
+
@@ -132,13 +105,10 @@ const props = defineProps({
const cardRoot = ref(null)
const stageEl = ref(null)
const overlayEl = ref(null)
-const particleCanvas = ref(null)
const phase = ref('idle') // 'idle' | 'storm' | 'packed' | 'merge' | 'burst' | 'cloud'
const hasPlayed = ref(false)
-const privacyMode = ref(false)
const accelerated = ref(true) // 默认加速
-const showParticles = ref(false)
// 通知父级 deck 隐藏顶部 UI
const deckChromeHidden = inject('deckChromeHidden', ref(false))
@@ -271,7 +241,6 @@ const bubbleSizeForText = (text, compact = false) => {
let stormTimer = null
let packedTimer = null
let mainTl = null
-let particleRaf = null
let hardStopTimer = null
let animationStartedAt = 0
let animationDeadlineAt = 0
@@ -299,18 +268,7 @@ const armHardStop = () => {
}, remain + 8)
}
-const stopParticles = () => {
- showParticles.value = false
- if (particleRaf) cancelAnimationFrame(particleRaf)
- particleRaf = null
- const c = particleCanvas.value
- if (c) {
- try {
- const ctx = c.getContext('2d')
- ctx?.clearRect?.(0, 0, c.width, c.height)
- } catch {}
- }
-}
+const stopParticles = () => {}
const killTimeline = () => {
if (mainTl) {
@@ -362,71 +320,6 @@ const isVisible = ref(false)
let io = null
const updateVisibility = (v) => { isVisible.value = !!v }
-const startParticles = (rng, centerX, centerY) => {
- if (!import.meta.client) return
- const canvas = particleCanvas.value
- if (!canvas || !curViewW || !curViewH) return
-
- const dpr = Math.max(1, Math.min(3, Number(window.devicePixelRatio || 1)))
- canvas.width = Math.max(1, Math.round(curViewW * dpr))
- canvas.height = Math.max(1, Math.round(curViewH * dpr))
- canvas.style.width = `${curViewW}px`
- canvas.style.height = `${curViewH}px`
- const ctx = canvas.getContext('2d')
- if (!ctx) return
- ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
-
- const N = 80
- const particles = []
- for (let i = 0; i < N; i += 1) {
- const ang = rng() * Math.PI * 2
- const sp = 120 + rng() * 320
- particles.push({
- x: centerX,
- y: centerY,
- vx: Math.cos(ang) * sp,
- vy: Math.sin(ang) * sp,
- size: 0.8 + rng() * 2.4,
- life: 1,
- color: rng() < 0.66 ? 'rgba(7,193,96,0.65)' : (rng() < 0.5 ? 'rgba(242,170,0,0.55)' : 'rgba(14,165,233,0.55)')
- })
- }
-
- showParticles.value = true
- const duration = 600
- let last = 0
- const started = performance.now()
-
- const tick = (now) => {
- const t = now - started
- const dt = last > 0 ? Math.min((now - last) / 1000, 0.05) : 0.016
- last = now
-
- ctx.clearRect(0, 0, curViewW, curViewH)
- const p = clamp(t / duration, 0, 1)
- const alpha = 1 - p
- for (const it of particles) {
- it.x += it.vx * dt
- it.y += it.vy * dt
- it.vx *= 0.86
- it.vy *= 0.86
- const a = alpha * 0.9
- ctx.fillStyle = it.color.replace(/[\d.]+\)$/g, `${a})`)
- ctx.beginPath()
- ctx.arc(it.x, it.y, it.size, 0, Math.PI * 2)
- ctx.fill()
- }
-
- if (t < duration) {
- particleRaf = requestAnimationFrame(tick)
- } else {
- stopParticles()
- }
- }
-
- particleRaf = requestAnimationFrame(tick)
-}
-
const maybeStart = () => {
if (!import.meta.client) return
detectReducedMotion()
@@ -849,10 +742,7 @@ const runMergeBurst = (rng, centerX, centerY) => {
opacity: 0,
scale: 0.92,
ease: 'power3.out',
- stagger: staggerBurst,
- onStart: () => {
- startParticles(rng, centerX, centerY)
- }
+ stagger: staggerBurst
})
const tlTotal = mainTl.totalDuration()
@@ -941,12 +831,6 @@ onBeforeUnmount(() => {
transform: translateY(-1px);
}
-.kw-chip--on {
- background: rgba(7, 193, 96, 0.12);
- border-color: rgba(7, 193, 96, 0.22);
- color: rgba(0, 0, 0, 0.75);
-}
-
.kw-bubble {
will-change: transform, opacity;
transform: translate3d(0, 0, 0);
diff --git a/frontend/components/wrapped/visualizations/KeywordWordCloud.vue b/frontend/components/wrapped/visualizations/KeywordWordCloud.vue
index 3bdca86..8457f88 100644
--- a/frontend/components/wrapped/visualizations/KeywordWordCloud.vue
+++ b/frontend/components/wrapped/visualizations/KeywordWordCloud.vue
@@ -6,98 +6,103 @@
:class="shouldAnimate ? 'kw-animate' : ''"
@pointerdown="onBgPointerDown"
>
-
-
-
-
-
-
-
暂无关键词
-
这一年你还没有足够的文字消息来生成词云。
-
-
-
-
-
-
-
-
-
- {{ selectedInfo.word }}
- · {{ formatInt(selectedInfo.count) }} 次
-
-
- 点击其它词,看看它出现的瞬间
-
-
-
+
+
-
-
- 没找到可展示的例句。
-
+
+
+
+
暂无常用语
+
这一年你还没有足够的重复短句来生成常用语词云。
+
+
-
-
-
-
-
-
- {{ seg.content }}
-
-
-
-
{{ m.raw }}
+
+
+
+
+
+
+
+ {{ selectedInfo.word }}
+ · {{ formatInt(selectedInfo.count) }} 次
+
+
+ 点击其它词,看看它出现的瞬间
+
+
+
+
+
+
+
+
+ 没找到可展示的例句。
+
+
+
+
+
+
+
+
+ {{ seg.content }}
+
+
+
+
{{ m.raw }}
+
+
-
-
-
-
-
+
+
+
+
-