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

View File

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