fix(home): 🐛 解决多次切换路由后页面卡顿的问题 #96 (#119)

卸载路由时清除requestAnimationFrame
This commit is contained in:
LOG1997
2025-12-16 23:36:44 +08:00
committed by GitHub
parent ec91a0de26
commit 92254cb750
2 changed files with 55 additions and 45 deletions

View File

@@ -1,71 +1,73 @@
// 判断颜色是否rgb或者rgba // 判断颜色是否rgb或者rgba
export function isRgbOrRgba(color: string) { export function isRgbOrRgba(color: string) {
return color.includes('rgb') || color.includes('rgba') return color.includes('rgb') || color.includes('rgba')
} }
// 判断是否hex形式 // 判断是否hex形式
export function isHex(color: string) { export function isHex(color: string) {
return color.includes('#') return color.includes('#')
} }
// 把hex颜色转成rgb数值类型 // 把hex颜色转成rgb数值类型
export function hexToRgba(hex: string) { export function hexToRgba(hex: string) {
const r = Number.parseInt(hex.slice(1, 3), 16) const r = Number.parseInt(hex.slice(1, 3), 16)
const g = Number.parseInt(hex.slice(3, 5), 16) const g = Number.parseInt(hex.slice(3, 5), 16)
const b = Number.parseInt(hex.slice(5, 7), 16) const b = Number.parseInt(hex.slice(5, 7), 16)
return { r, g, b } return { r, g, b }
} }
// 把rgb数组转化成r g b 数值 // 把rgb数组转化成r g b 数值
export function rgbToRgba(rgb: string) { export function rgbToRgba(rgb: string) {
const rgbArr = rgb.split('(')[1].split(')')[0].split(',') const rgbArr = rgb.split('(')[1].split(')')[0].split(',')
return { r: rgbArr[0], g: rgbArr[1], b: rgbArr[2] } return { r: rgbArr[0], g: rgbArr[1], b: rgbArr[2] }
} }
// 组成rgb颜色添加透明度 // 组成rgb颜色添加透明度
export function rgba(color: string, opacity: number) { export function rgba(color: string, opacity: number) {
opacity = opacity || 1 opacity = opacity || 1
let rgbaStr = '' let rgbaStr = ''
// 判断是否是hex颜色 // 判断是否是hex颜色
if (isHex(color)) { if (isHex(color)) {
const { r, g, b } = hexToRgba(color) const { r, g, b } = hexToRgba(color)
rgbaStr = `rgba(${r},${g},${b},${opacity})` rgbaStr = `rgba(${r},${g},${b},${opacity})`
} }
else { else {
const { r, g, b } = rgbToRgba(color) const { r, g, b } = rgbToRgba(color)
rgbaStr = `rgba(${r},${g},${b},${opacity})` rgbaStr = `rgba(${r},${g},${b},${opacity})`
} }
return rgbaStr return rgbaStr
} }
export function rgbToHex(color:string) { export function rgbToHex(color: string) {
// 去掉字符串中的空格 // 去掉字符串中的空格
color = color.replace(/\s+/g, ''); color = color.replace(/\s+/g, '');
if (isHex(color)) {
return color
}
// 匹配rgba或rgb格式的字符串
const rgbaMatch = color.match(/^rgba?\((\d+),(\d+),(\d+),?(\d*\.?\d+)?\)$/i);
if (!rgbaMatch) {
throw new Error('Invalid color format');
}
// 匹配rgba或rgb格式的字符串 const r = parseInt(rgbaMatch[1], 10);
const rgbaMatch = color.match(/^rgba?\((\d+),(\d+),(\d+),?(\d*\.?\d+)?\)$/i); const g = parseInt(rgbaMatch[2], 10);
if (!rgbaMatch) { const b = parseInt(rgbaMatch[3], 10);
throw new Error('Invalid color format'); const a = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : undefined;
}
const r = parseInt(rgbaMatch[1], 10); // 将RGB值转换为十六进制
const g = parseInt(rgbaMatch[2], 10); let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
const b = parseInt(rgbaMatch[3], 10);
const a = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : undefined;
// 将RGB值转换为十六进制 // 如果提供了alpha值则将其转换为十六进制并附加到结果中
let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); if (a !== undefined) {
let alphaHex = Math.round(a * 255).toString(16).toUpperCase();
if (alphaHex.length === 1) {
alphaHex = "0" + alphaHex; // 确保alpha值是两位数
}
hex += alphaHex;
}
// 如果提供了alpha值则将其转换为十六进制并附加到结果中 return hex;
if (a !== undefined) {
let alphaHex = Math.round(a * 255).toString(16).toUpperCase();
if (alphaHex.length === 1) {
alphaHex = "0" + alphaHex; // 确保alpha值是两位数
}
hex += alphaHex;
}
return hex;
} }

View File

@@ -52,6 +52,7 @@ export function useViewModel() {
const personPool = ref<IPersonConfig[]>([]) const personPool = ref<IPersonConfig[]>([])
const intervalTimer = ref<any>(null) const intervalTimer = ref<any>(null)
const isInitialDone = ref<boolean>(false) const isInitialDone = ref<boolean>(false)
const animationFrameId = ref<any>(null)
function initThreeJs() { function initThreeJs() {
const felidView = 40 const felidView = 40
@@ -214,7 +215,7 @@ export function useViewModel() {
} }
// 设置自动旋转 // 设置自动旋转
// 设置相机位置 // 设置相机位置
requestAnimationFrame(animation) animationFrameId.value = requestAnimationFrame(animation)
} }
/** /**
* @description: 旋转的动画 * @description: 旋转的动画
@@ -531,6 +532,13 @@ export function useViewModel() {
* @description: 清理资源,避免内存溢出 * @description: 清理资源,避免内存溢出
*/ */
function cleanup() { function cleanup() {
// 停止所有Tween动画
TWEEN.removeAll()
// 清理动画循环
if ((window as any).cancelAnimationFrame) {
(window as any).cancelAnimationFrame(animationFrameId.value)
}
clearInterval(intervalTimer.value) clearInterval(intervalTimer.value)
intervalTimer.value = null intervalTimer.value = null
if (scene.value) { if (scene.value) {