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 @@ 你的话,正在涌来。

@@ -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 }} +
+
-
-
- -
- + + +
+ -