refactor(页面布局): 重构页面布局和样式

- 移除未使用的HTML文件和冗余代码
- 调整侧边栏位置和样式
- 优化标签云组件交互和性能
- 更新播放器控件样式和功能
- 改进预览弹窗的背景透明度
- 添加favicon图标
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-09-22 17:49:06 +08:00
parent 0e0d977c3b
commit 4087c429fa
14 changed files with 1302 additions and 1127 deletions

380
static/js/tagcloud-3.1.js Normal file
View File

@@ -0,0 +1,380 @@
/*
* 3D标签云无缩放版
* 功能鼠标移入标签静止、自动3D旋转、GPU加速移除所有放大缩小效果
* 说明radius控制滚动区域基于translate3d实现3D定位全程保持标签原始尺寸
* 版本3.1
* */
window.tagCloud = (function (win, doc) {
function isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
function TagCloud(options) {
var self = this;
self.config = TagCloud._getConfig(options);
self.box = self.config.element;
self.fontsize = self.config.fontsize;
self.animDuration = self.config.animDuration;
self.perspective = self.config.perspective;
// 初始化滚动区域(半径与比例)
if (Number.isInteger(self.config.radius)) {
self._radiusX = self._radiusY = self.config.radius;
} else if (self.config.radius instanceof Array) {
self._radiusX = self.config.radius.length >= 1 ? self.config.radius[0] : 60;
self._radiusY = self.config.radius.length >= 2 ? self.config.radius[1] : self._radiusX;
}
self.radius = Math.max(self._radiusX, self._radiusY);
const ratio = Math.round((self._radiusX * 10) / self._radiusY) / 10;
self.ratioX = ratio < 1 ? ratio : 1;
self.ratioY = ratio > 1 ? ratio : 1;
// 基础参数
self.depth = 2 * self.radius;
self.mspeed = TagCloud._getMsSpeed(self.config.mspeed);
self.ispeed = TagCloud._getIsSpeed(self.config.ispeed);
self.items = self._getItems();
self.direction = self.config.direction;
self.keep = self.config.keep;
// 状态变量
self.active = false;
self.mouseX = 0;
self.mouseY = 0;
self.index = -1;
self.keyframeNames = [];
// 初始化容器样式3D透视核心
self.box.style.position = "relative";
self.box.style.visibility = "visible";
self.box.style.overflow = "hidden";
self.box.style.perspective = `${self.perspective}px`;
self.box.style.transformStyle = "preserve-3d";
// 事件绑定
self._bindEvents();
// 生成关键帧与动画
self._generateAllKeyframes();
self._applyAnimations();
// 实时更新
self._update = self._update.bind(self);
requestAnimationFrame(self._update);
}
// 静态属性与方法
TagCloud.boxs = [];
// 数组indexOf兼容
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (elt) {
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = from < 0 ? Math.ceil(from) : Math.floor(from);
if (from < 0) from += len;
for (; from < len; from++) {
if (from in this && this[from] === elt) return from;
}
return -1;
};
}
// querySelectorAll兼容
if (!doc.querySelectorAll) {
doc.querySelectorAll = function (selectors) {
var style = doc.createElement("style"),
elements = [],
element;
doc.documentElement.firstChild.appendChild(style);
doc._qsa = [];
style.styleSheet.cssText = selectors + "{x-qsa:expression(document._qsa && document._qsa.push(this))}";
window.scrollBy(0, 0);
style.parentNode.removeChild(style);
while (doc._qsa.length) {
element = doc._qsa.shift();
element.style.removeAttribute("x-qsa");
elements.push(element);
}
doc._qsa = null;
return elements;
};
}
// 配置合并移除hoverScale配置
TagCloud._getConfig = function (config) {
const defaultConfig = {
selector: ".tagcloud",
fontsize: 16,
radius: [80, 60],
mspeed: "normal",
ispeed: "normal",
direction: 135,
keep: true,
multicolour: true,
animDuration: 15,
perspective: 800
};
if (isObject(config)) {
for (let i in config) {
if (config.hasOwnProperty(i) && i !== "hoverScale") { // 禁止传入缩放相关配置
defaultConfig[i] = config[i];
}
}
}
return defaultConfig;
};
// 滚动最大速度映射
TagCloud._getMsSpeed = function (mspeed) {
const speedMap = { slow: 1.2, normal: 5, fast: 4 };
return speedMap[mspeed] || 2.5;
};
// 初始速度映射
TagCloud._getIsSpeed = function (ispeed) {
const speedMap = { slow: 8, normal: 20, fast: 40 };
return speedMap[ispeed] || 20;
};
// 角度转正弦余弦集合
TagCloud._getSc = function (a, b) {
const l = Math.PI / 180;
return [Math.sin(a * l), Math.cos(a * l), Math.sin(b * l), Math.cos(b * l)];
};
// 事件绑定兼容
TagCloud._on = function (ele, eve, handler, cap = false) {
if (ele.addEventListener) {
ele.addEventListener(eve, handler, cap);
} else if (ele.attachEvent) {
ele.attachEvent("on" + eve, handler);
} else {
ele["on" + eve] = handler;
}
};
// 原型方法
TagCloud.prototype = {
constructor: TagCloud,
// 获取标签数据(移除缩放相关逻辑)
_getItems: function () {
const self = this;
const items = [];
const children = self.box.children;
const len = children.length;
for (let i = 0; i < len; i++) {
const element = children[i];
// 强制设置标签字体大小(固定,不随深度变化)
// element.style.fontSize = `${self.fontsize}px`;
// element.style.lineHeight = "1.5"; // 固定行高,避免尺寸变化
const angle = {
phi: Math.acos(-1 + (2 * i + 1) / len),
theta: Math.sqrt((len + 1) * Math.PI) * Math.acos(-1 + (2 * i + 1) / len)
};
// 初始3D坐标球面映射
const x = (self.radius / 2) * 1.5 * Math.cos(angle.theta) * Math.sin(angle.phi) * self.ratioX;
const y = (self.radius / 2) * 1.5 * Math.sin(angle.theta) * Math.sin(angle.phi) / self.ratioY;
const z = (self.radius / 2) * 1.5 * Math.cos(angle.phi);
// 彩色标签配置
if (self.config.multicolour) {
const hue = Math.round(Math.random() * 360);
const lightness = 30 + Math.round(Math.random() * 30);
element.style.color = `hsl(${hue}, 100%, ${lightness}%)`;
}
// 标签基础样式移除scale过渡固定尺寸
element.style.position = "absolute";
element.style.transformStyle = "preserve-3d";
element.style.transition = "transform 0.3s ease, z-index 0.3s ease, opacity 0.3s ease"; // 仅保留位置、层级、透明度过渡
element.style.cursor = "pointer";
element.style.transform = "scale(1)"; // 强制固定缩放为1无放大缩小
element.index = i;
items.push({
element,
angle,
x,
y,
z,
offsetWidth: element.offsetWidth,
offsetHeight: element.offsetHeight
});
}
return items;
},
// 绑定交互事件(无缩放逻辑)
_bindEvents: function () {
const self = this;
// 容器鼠标移入/移出
TagCloud._on(self.box, "mouseover", () => { self.active = true; });
TagCloud._on(self.box, "mouseout", () => { self.active = false; });
// 鼠标移动
const target = self.config.keep ? win : self.box;
TagCloud._on(target, "mousemove", (ev) => {
const oEvent = win.event || ev;
const rect = self.box.getBoundingClientRect();
self.mouseX = (oEvent.clientX - (rect.left + rect.width / 2)) / 8;
self.mouseY = (oEvent.clientY - (rect.top + rect.height / 2)) / 8;
});
// 标签鼠标移入/移出(仅静止、置顶,无放大)
self.items.forEach(item => {
TagCloud._on(item.element, "mouseover", function () {
self.index = this.index;
this.style.zIndex = 999; // 仅置顶,不放大
});
TagCloud._on(item.element, "mouseout", function () {
self.index = -1;
this.style.zIndex = "";
});
});
},
// 生成关键帧移除缩放逻辑固定scale=1
_generateKeyframe: function (itemIndex) {
const self = this;
const keyframeName = `tagCloudAnim_${Date.now()}_${itemIndex}`;
const styleSheet = doc.createElement("style");
let keyframeCSS = `@keyframes ${keyframeName} {`;
// 拆分360°旋转为20个关键帧
for (let deg = 0; deg <= 360; deg += 18) {
const rad = deg * Math.PI / 180;
const item = self.items[itemIndex];
const sc = TagCloud._getSc(
Math.sin(rad) * self.mspeed,
Math.cos(rad) * self.mspeed
);
// 实时3D坐标计算
const rx1 = item.x;
const ry1 = item.y * sc[1] + item.z * -sc[0];
const rz1 = item.y * sc[0] + item.z * sc[1];
const rx2 = rx1 * sc[3] + rz1 * sc[2];
const ry2 = ry1;
const rz2 = rz1 * sc[3] - rx1 * sc[2];
// 固定透明度(或按深度微调,不影响尺寸)
const per = self.depth / (self.depth + rz2);
const opacity = Math.max(0.5, per); // 仅调整透明度,无缩放
// 容器中心偏移
const centerX = (self.box.offsetWidth - item.offsetWidth) / 2;
const centerY = (self.box.offsetHeight - item.offsetHeight) / 2;
// 关键帧内容固定scale=1仅保留translate3d和opacity
const percent = (deg / 360) * 100;
keyframeCSS += `${percent}% {
transform: translate(${rx2 + centerX}px, ${ry2 + centerY}px) scale(1);
opacity: ${opacity};
z-index: ${Math.ceil(per * 10)};
}`;
}
keyframeCSS += `}`;
styleSheet.innerHTML = keyframeCSS;
doc.head.appendChild(styleSheet);
return keyframeName;
},
// 生成所有标签的关键帧
_generateAllKeyframes: function () {
const self = this;
self.keyframeNames = self.items.map((_, index) => {
return self._generateKeyframe(index);
});
},
// 为标签应用动画(无缩放)
_applyAnimations: function () {
const self = this;
self.items.forEach((item, index) => {
const animName = self.keyframeNames[index];
// 应用动画固定scale=1仅translate3d和opacity变化
item.element.style.animation = `${animName} ${self.animDuration}s linear infinite`;
item.element.style.transform = `scale(1)`; // 双重保障,防止缩放
});
},
// 实时更新(仅静止、调整动画速度,无放大缩小)
_update: function () {
const self = this;
if (self.index === -1 && !self.active) {
requestAnimationFrame(self._update);
return;
}
// 选中标签:仅静止、置顶、保持原始尺寸
if (self.index !== -1) {
const item = self.items[self.index];
const centerX = (self.box.offsetWidth - item.offsetWidth) / 2;
const centerY = (self.box.offsetHeight - item.offsetHeight) / 2;
// 暂停动画+固定位置+scale=1
item.element.style.animationPlayState = "paused";
item.element.style.transform = `translate(${centerX}px, ${centerY}px) scale(1)`;
item.element.style.opacity = 1;
} else {
// 鼠标交互:仅调整动画速度,无缩放
// self.items.forEach((item, index) => {
// item.element.style.animationPlayState = "running";
// const newDuration = self.animDuration - Math.abs(self.mouseX + self.mouseY) / 5;
// const animName = self.keyframeNames[index];
// item.element.style.animation = `${animName} ${Math.max(8, newDuration)}s linear infinite`;
// item.element.style.transform = `scale(1)`; // 确保无缩放
// });
}
requestAnimationFrame(self._update);
},
// 销毁实例
destroy: function () {
const self = this;
// 移除所有动画样式
const styles = doc.querySelectorAll('style');
styles.forEach(style => {
if (style.innerHTML.includes('tagCloudAnim_')) {
doc.head.removeChild(style);
}
});
// 移除事件监听
self.box.onmouseover = null;
self.box.onmouseout = null;
self.items.forEach(item => {
item.element.onmouseover = null;
item.element.onmouseout = null;
item.element.style.animation = null;
item.element.style.transform = "scale(1)";
});
// 从实例数组中移除
const idx = TagCloud.boxs.indexOf(self.box);
if (idx !== -1) TagCloud.boxs.splice(idx, 1);
}
};
// 工厂函数
return function (options = {}) {
const selector = options.selector || ".tagcloud";
const elements = doc.querySelectorAll(selector);
const instances = [];
elements.forEach(element => {
if (TagCloud.boxs.indexOf(element) === -1) {
TagCloud.boxs.push(element);
const instance = new TagCloud({ ...options, element });
instances.push(instance);
}
});
return instances;
};
})(window, document);