格式化代码并添加视角高度控制以及视角范围控制

This commit is contained in:
wzy-warehouse
2026-04-13 10:30:03 +08:00
parent 83f8fec3a4
commit 5eb71642d2
46 changed files with 2084 additions and 1535 deletions
+79 -66
View File
@@ -13,46 +13,48 @@ export const Utils = {
debounce: function <This, T extends unknown[], R = void>(
func: (this: This, ...args: T) => R,
delay: number = 500,
immediate: boolean = false,
immediate: boolean = false
) {
let timer: number | null = null
let timer: number | null = null;
// 用泛型This指定this类型
return function (this: This, ...args: T): void {
if (timer) clearTimeout(timer)
if (timer) clearTimeout(timer);
// 立即执行逻辑
if (immediate && !timer) {
func.apply(this, args)
func.apply(this, args);
}
// 重新设置定时器
timer = window.setTimeout(() => {
if (!immediate) {
func.apply(this, args)
func.apply(this, args);
}
timer = null
}, delay)
}
timer = null;
}, delay);
};
},
formatDate: (format: string, date: Date = new Date()): string => {
// 基础时间数据
const year = date.getFullYear()
const month = date.getMonth() + 1 // 月份0-11,需+1
const day = date.getDate()
const hours24 = date.getHours()
const hours12 = hours24 % 12 || 12 // 12小时制处理(0→12
const minutes = date.getMinutes()
const seconds = date.getSeconds()
const weekNum = date.getDay() // 星期0-60=周日)
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月份0-11,需+1
const day = date.getDate();
const hours24 = date.getHours();
const hours12 = hours24 % 12 || 12; // 12小时制处理(0→12
const minutes = date.getMinutes();
const seconds = date.getSeconds();
const weekNum = date.getDay(); // 星期0-60=周日)
// 星期映射配置
const weekMaps = {
ddd: ['日', '一', '二', '三', '四', '五', '六'].map((day) => `星期${day}`),
ddd: ['日', '一', '二', '三', '四', '五', '六'].map(
(day) => `星期${day}`
),
dd: ['日', '一', '二', '三', '四', '五', '六'].map((day) => `${day}`),
d: [0, 1, 2, 3, 4, 5, 6],
}
};
// 占位符替换规则(顺序:长占位符优先,避免冲突)
const replaceRules = [
@@ -73,12 +75,12 @@ export const Utils = {
{ regex: /ddd/g, value: weekMaps.ddd[weekNum] },
{ regex: /dd/g, value: weekMaps.dd[weekNum] },
{ regex: /d/g, value: weekMaps.d[weekNum] },
]
];
// 执行替换
return replaceRules.reduce((result, { regex, value }) => {
return result.replace(regex, String(value ?? ''))
}, format)
return result.replace(regex, String(value ?? ''));
}, format);
},
/**
@@ -91,115 +93,121 @@ export const Utils = {
deepClone: <T>(source: T, hash = new WeakMap<object, unknown>()): T => {
// 处理 null 或 undefined
if (source === null || source === undefined) {
return source
return source;
}
// 处理原始类型(string, number, boolean, symbol, bigint, function
if (typeof source !== 'object' && typeof source !== 'function') {
return source
return source;
}
// 处理函数 - 直接返回原函数引用(通常不需要克隆函数)
if (typeof source === 'function') {
return source
return source;
}
// 解决循环引用
if (hash.has(source)) {
return hash.get(source) as T
return hash.get(source) as T;
}
// 处理 Date 对象
if (source instanceof Date) {
const cloned = new Date(source.getTime()) as T
hash.set(source, cloned)
return cloned
const cloned = new Date(source.getTime()) as T;
hash.set(source, cloned);
return cloned;
}
// 处理 RegExp 对象
if (source instanceof RegExp) {
const cloned = new RegExp(source.source, source.flags)
cloned.lastIndex = source.lastIndex // 安全访问
return cloned as unknown as T
const cloned = new RegExp(source.source, source.flags);
cloned.lastIndex = source.lastIndex; // 安全访问
return cloned as unknown as T;
}
// 处理 Map 对象
if (source instanceof Map) {
const cloned = new Map()
hash.set(source, cloned)
const cloned = new Map();
hash.set(source, cloned);
source.forEach((value, key) => {
cloned.set(Utils.deepClone(key, hash), Utils.deepClone(value, hash))
})
return cloned as T
cloned.set(Utils.deepClone(key, hash), Utils.deepClone(value, hash));
});
return cloned as T;
}
// 处理 Set 对象
if (source instanceof Set) {
const cloned = new Set<unknown>()
hash.set(source, cloned)
const cloned = new Set<unknown>();
hash.set(source, cloned);
for (const value of source.values()) {
cloned.add(Utils.deepClone(value, hash))
cloned.add(Utils.deepClone(value, hash));
}
return cloned as T
return cloned as T;
}
// 处理 ArrayBuffer
if (source instanceof ArrayBuffer) {
const cloned = source.slice(0) as T
hash.set(source, cloned)
return cloned
const cloned = source.slice(0) as T;
hash.set(source, cloned);
return cloned;
}
// 处理数组
if (Array.isArray(source)) {
const cloned: T[] = []
hash.set(source, cloned)
const cloned: T[] = [];
hash.set(source, cloned);
for (let i = 0; i < source.length; i++) {
cloned[i] = Utils.deepClone(source[i], hash)
cloned[i] = Utils.deepClone(source[i], hash);
}
return cloned as T
return cloned as T;
}
// 处理普通对象
if (typeof source === 'object') {
// 处理 Error 对象
if (source instanceof Error) {
const cloned = new Error(source.message)
cloned.stack = source.stack
cloned.name = source.name
hash.set(source, cloned)
return cloned as T
const cloned = new Error(source.message);
cloned.stack = source.stack;
cloned.name = source.name;
hash.set(source, cloned);
return cloned as T;
}
// 处理其他对象
const cloned: { [key: string | symbol]: unknown } = {}
hash.set(source, cloned)
const cloned: { [key: string | symbol]: unknown } = {};
hash.set(source, cloned);
// 获取对象的所有属性(包括不可枚举的属性和 Symbol)
const keys = [...Object.getOwnPropertyNames(source), ...Object.getOwnPropertySymbols(source)]
const keys = [
...Object.getOwnPropertyNames(source),
...Object.getOwnPropertySymbols(source),
];
for (const key of keys) {
const descriptor = Object.getOwnPropertyDescriptor(source, key)
const descriptor = Object.getOwnPropertyDescriptor(source, key);
// 如果是访问器属性
if (descriptor && descriptor.get) {
Object.defineProperty(cloned, key, descriptor)
Object.defineProperty(cloned, key, descriptor);
} else {
// 如果是数据属性
cloned[key] = Utils.deepClone((source as { [key: string | symbol]: unknown })[key], hash)
cloned[key] = Utils.deepClone(
(source as { [key: string | symbol]: unknown })[key],
hash
);
}
}
// 处理原型链
const proto = Object.getPrototypeOf(source)
const proto = Object.getPrototypeOf(source);
if (proto && proto !== Object.prototype) {
Object.setPrototypeOf(cloned, proto)
Object.setPrototypeOf(cloned, proto);
}
return cloned as T
return cloned as T;
}
// 对于其他无法处理的情况,返回原值
return source
return source;
},
/**
@@ -209,8 +217,13 @@ export const Utils = {
* @param {number} width - 元素的宽度
* @param {number} height - 元素的高度
* @returns {[number, number]} 调整后的 [newX, newY]
*/
keepWithinScreen: (offsetX: number, offsetY: number, width: number, height: number) => {
*/
keepWithinScreen: (
offsetX: number,
offsetY: number,
width: number,
height: number
) => {
const viewportW = window.innerWidth;
const viewportH = window.innerHeight;
@@ -224,5 +237,5 @@ export const Utils = {
const newY = Math.min(Math.max(offsetY, 0), maxY);
return [newX, newY];
}
}
},
};