This commit is contained in:
2025-11-20 14:10:00 +08:00
parent bca67b7f25
commit 5e2f8ac169

View File

@@ -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;
}
});
</script>
<style scoped>