diff --git a/pages/index/components/AIMatch.vue b/pages/index/components/AIMatch.vue index 473f5a8..251ee15 100644 --- a/pages/index/components/AIMatch.vue +++ b/pages/index/components/AIMatch.vue @@ -16,7 +16,7 @@ import * as PIXI from "pixi.js"; const appRef = ref(null); // 存储 PIXI 应用实例 -// 标签数据:包含名称、颜色、大小、位置(角度、半径) +// 名称、颜色、大小、位置(角度、半径) const mockTags = [ { name: "医生", @@ -34,7 +34,7 @@ const mockTags = [ size: 14, opacity: 1, angle: -Math.PI / 2, // 12点方向 - radius: 60, + radius: 68, tailRotation: Math.PI / 2, // 拖尾向下 }, { @@ -43,8 +43,8 @@ const mockTags = [ fontColor: 0xf86e6e, size: 11.5, opacity: 1, - angle: -Math.PI / 4, // 1点方向 - radius: 115, + angle: -Math.PI / 4.2, // 1点方向 + radius: 125, tailRotation: (3 * Math.PI) / 4, // 拖尾向左下 }, { @@ -69,10 +69,10 @@ const mockTags = [ }, { name: "程序员", - bgColor: 0xff9d57, + bgColor: 0xffd4b6, fontColor: 0xffffff, size: 14.5, - opacity: 0.6, + opacity: 1, angle: Math.PI / 9, // 4点方向 radius: 120, tailRotation: (5 * Math.PI) / 4, // 拖尾向左上 @@ -113,7 +113,7 @@ const mockTags = [ fontColor: 0xffffff, size: 15, opacity: 1, - angle: (6.3 * Math.PI) / 6, // 10点方向 + angle: (6.3 * Math.PI) / 5.9, // 10点方向 radius: 110, tailRotation: Math.PI / 4, // 拖尾向右下 }, @@ -123,8 +123,8 @@ const mockTags = [ fontColor: 0xfbc55f, size: 13, opacity: 1, - angle: (7.2 * Math.PI) / 6, // 11点方向 - radius: 115, + angle: (7.2 * Math.PI) / 5.9, // 11点方向 + radius: 120, tailRotation: Math.PI / 4, // 拖尾向右下 }, ]; @@ -135,7 +135,6 @@ onMounted(async () => { const canvas = document.getElementById("matchCanvas"); const sw = canvas.clientWidth; const sh = canvas.clientHeight; - const app = new PIXI.Application({ backgroundAlpha: 0, antialias: true, @@ -148,11 +147,11 @@ onMounted(async () => { canvas.appendChild(app.view); - // 标签容器(管理所有标签) + // 标签容器( const tagsContainer = new PIXI.Container(); app.stage.addChild(tagsContainer); - // 存储已放置标签的信息(位置、尺寸、浮动动画参数) + // 存储已放置标签的信息 const placedTags = []; for (let i = 0; i < mockTags.length; i++) { @@ -167,15 +166,12 @@ onMounted(async () => { let floatSpeed = 0.01 + Math.random() * 0.02; let floatRange = 2 + Math.random() * 2; - // 为标签添加彗星拖尾效果 + // 拖尾效果 if (radius > 0) { - // 中心标签不需要拖尾 const tail = createCometTail(tagData.bgColor, tailRotation, tag); - - // 修正:使用 addChildAt 将拖尾添加到最底层 + // 使用 addChildAt tag.addChildAt(tail, 0); - - // 为拖尾添加单独的动画 + // 拖尾动画 app.ticker.add(() => { if (tail.updateTail) { tail.updateTail(); @@ -183,7 +179,7 @@ onMounted(async () => { }); } - // 使用PIXI ticker进行动画 + // 上下浮动动画 app.ticker.add(() => { floatOffset += floatSpeed; tag.y = originalY + Math.sin(floatOffset) * floatRange; @@ -194,19 +190,11 @@ onMounted(async () => { } }); -// 销毁时清理资源 -onUnmounted(() => { - if (appRef.value) { - appRef.value.destroy(true, true); - appRef.value = null; - } -}); - -// 创建彗星拖尾效果 +// 创建拖尾 function createCometTail(bgColor, tailRotation, tag) { const tailGroup = new PIXI.Container(); - // 拖尾直接放在标签中心位置 + // 拖尾位置 tailGroup.x = 0; tailGroup.y = 0; @@ -222,7 +210,7 @@ function createCometTail(bgColor, tailRotation, tag) { let breathPhase = Math.random() * Math.PI * 2; const breathSpeed = 0.04; - // 更新拖尾的呼吸动画 + // 更新拖尾呼吸动画 tailGroup.updateTail = () => { breathPhase += breathSpeed; const breathScale = 0.85 + 0.15 * Math.sin(breathPhase); @@ -230,13 +218,12 @@ function createCometTail(bgColor, tailRotation, tag) { // 绘制梯形拖尾 const currentLength = baseLength * breathScale; - // 计算拖尾的四个顶点 - // 长边在标签中心,水平方向(与标签长边平行) + // 长边在标签中心 水平方向 const startLeft = { x: -startWidth / 2, y: 0 }; const startRight = { x: startWidth / 2, y: 0 }; - // 短边在拖尾方向,保持水平 + // 短边在拖尾方向 保持水平 const endCenter = { x: Math.cos(tailRotation) * currentLength, y: Math.sin(tailRotation) * currentLength, @@ -276,7 +263,7 @@ function createCometTail(bgColor, tailRotation, tag) { y: startRight.y * (1 - nextProgress) + endRight.y * nextProgress, }; - // 透明度从0.4渐变到0 + // 透明度渐变 const segmentAlpha = 0.4 * (1 - progress); tail.beginFill(bgColor, segmentAlpha); @@ -289,19 +276,19 @@ function createCometTail(bgColor, tailRotation, tag) { } }; - // 初始绘制 + // 绘制 tailGroup.updateTail(); return tailGroup; } -// 创建单个标签(背景+文本) +// 创建标签 function createTag(tagData, x, y, placedTags, app, index) { const tagGroup = new PIXI.Container(); tagGroup.x = x; tagGroup.y = y; - // 先创建文本以测量宽度 + // 创建文本测量宽度 const text = new PIXI.Text(tagData.name, { fontFamily: "Arial", fontSize: tagData.size, @@ -309,7 +296,6 @@ function createTag(tagData, x, y, placedTags, app, index) { }); text.anchor.set(0.5); - // 根据文字个数动态计算宽度 const padding = 10; const charWidth = tagData.size * 1.5; const charHeight = tagData.size * 1.3; @@ -320,7 +306,7 @@ function createTag(tagData, x, y, placedTags, app, index) { const height = charHeight + padding; - // 背景(圆角矩形) + // 背景 const bg = new PIXI.Graphics(); bg.beginFill(tagData.bgColor, tagData.opacity ?? 1); bg.drawRoundedRect(-width / 2, -height / 2, width, height, 20); @@ -332,6 +318,13 @@ function createTag(tagData, x, y, placedTags, app, index) { return tagGroup; } + +onUnmounted(() => { + if (appRef.value) { + appRef.value.destroy(true, true); + appRef.value = null; + } +});