import { size, view, Node, UITransform, screen, ImageAsset, SpriteFrame, Texture2D, sys, assetManager } from "cc"; /**工具*/ class ch_util { private static _instance: ch_util; public static getInstance(): ch_util { if (!this._instance) this._instance = new ch_util(); return this._instance; } /** * 随机数 (包含min,不包含max) * @param min * @param max * @param isInt * @return {*} */ public getRandom(min: number = 0, max: number = 1): number { if (min == null) min = 0; if (max == null) max = 1; if (min === max) return min; return min + (Math.random() * (max - min)); } /** * 随机整数-不包含最大值 * @param min * @param max * @return {*} */ public getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.ceil(max); return Math.floor(Math.random() * (max - min)) + min; } /** 生成随机整数 -1 或 1*/ public getRandomDir(): -1 | 1 { return Math.floor(Math.random() * 2) === 0 ? -1 : 1; } /** * 在指定数组中随机取出N个不重复的数据 * @param resArr * @param ranNum * @returns {Array} */ public getRandomDiffValueFromArr(resArr: Array, ranNum: number): Array { let arr = new Array(); let result = new Array(); if (!resArr || resArr.length <= 0 || ranNum <= 0) { return result; } for (let i = 0; i < resArr.length; i++) { arr.push(resArr[i]); } if (ranNum >= arr.length) return arr; ranNum = Math.min(ranNum, arr.length - 1); for (let i = 0; i < ranNum; i++) { let ran = this.getRandomInt(0, arr.length - 1); result.push(arr.splice(ran, 1)[0]); } return result; } /** * 取小数位 * @param decimal 小数 * @param places 位数 * @return {number} */ public numberToDecimal(decimal: number, places: number): number { let round: number = Math.pow(10, places); return Math.round(decimal * round) / round; } public parse(text: string, reciver?: (key: any, value: any) => any): any { try { return JSON.parse(text, reciver); } catch (error) { //ch_log.error(error); return null; } } public stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number) { try { return JSON.stringify(value, replacer, space); } catch (error) { return null; } } /** * 判断字符是否为双字节字符(如中文字符) * @param string 原字符串 */ public str_isDoubleWord(string: string): boolean { return /[^\x00-\xff]/.test(string); } /** * 是否为空 * @param str */ public str_isEmpty(str: string): boolean { if (str == null || str == undefined || str.length == 0) { return true; } return false; } /** * 转美式计数字符串 * @param value 数字 * @example * 123456789 = 123,456,789 */ public numberTotPermil(value: number): string { return value.toLocaleString(); } private readonly _k: number = 1000; private readonly _k_sizes_en: string[] = ['', 'K', 'M', 'G', 'T', 'P', 'E']; private readonly _k_sizes_cn: string[] = ['', '千', '百万', '十亿', '万亿', '拍(千万亿)', '艾(十亿亿)']; private readonly _w: number = 10000; private readonly _w_sizes_en: string[] = ['', 'W', 'M', 'B', 'T']; private readonly _w_sizes_cn: string[] = ['', '万', '亿', '万亿']; /** * 通用单位转换方法 */ private convertNumber(value: number, base: number, sizes: string[], fixed: number): string { if (value < base) return value.toString(); const i = Math.floor(Math.log(value) / Math.log(base)); const r = value / Math.pow(base, i); if (i >= sizes.length) return value.toString(); return `${r.toFixed(fixed)}${sizes[i]}`; } /** * 转单位计数(默认英文) * @param value 数字 * @param fixed 保留小数位数 * @param isEn 是否英文 * @example * 12345 = 12.35K */ public numberToThousand(value: number, fixed: number = 2, isEn: boolean = true): string { const sizes = isEn ? this._k_sizes_en : this._k_sizes_cn; return this.convertNumber(value, this._k, sizes, fixed); } /** * 转单位计数(默认中文) * @param value 数字 * @param fixed 保留小数位数 * @param isEn 是否英文 * @example * 12345 = 1.23万 */ public numberToTenThousand(value: number, fixed: number = 2, isEn: boolean = false): string { const sizes = isEn ? this._w_sizes_en : this._w_sizes_cn; return this.convertNumber(value, this._w, sizes, fixed); } /**获取一个唯一标识的字符串 */ public guid() { let guid: string = Math.random().toString(36).substring(2); return guid; } /**排序一个json Object*/ public obj_sort(obj: any): any { let sorted_keys: string[] = Object.keys(obj).sort(); let new_obj = {}; for (let i = 0; i < sorted_keys.length; i++) { const key = sorted_keys[i]; const value = obj[key]; const t = this.obj_get_value_type(value); new_obj[key] = t == 'object' ? this.obj_sort(value) : value; } return new_obj; } /**获取一个josn值的类型*/ public obj_get_value_type(value: any): string { let type: string; if (value === null) { type = 'null'; } else { type = typeof value; } // 如果是对象或数组,还可以进一步判断 if (type === 'object') { if (Array.isArray(value)) { type = 'array'; } //else if (value instanceof Date) { type = 'date'; } } return type; } /** * 判断指定的值是否为对象 * @param value 值 */ public valueIsObject(value: any): boolean { return Object.prototype.toString.call(value) === '[object Object]'; } /** * 深拷贝 * @param target 目标 */ /** 克隆对象 */ public obj_clone(target_: T, record_set = new Set()): T { let result: any; switch (typeof target_) { case "object": { // 数组:遍历拷贝 if (Array.isArray(target_)) { if (record_set.has(target_)) { return target_; } record_set.add(target_); result = []; for (let k_n = 0; k_n < target_.length; ++k_n) { // 递归克隆数组中的每一项 result.push(this.obj_clone(target_[k_n], record_set)); } } // null:直接赋值 else if (target_ === null) { result = null; } // RegExp:直接赋值 else if ((target_ as any).constructor === RegExp) { result = target_; } // 普通对象:循环递归赋值对象的所有值 else { if (record_set.has(target_)) { return target_; } record_set.add(target_); result = {}; for (const k_s in target_) { result[k_s] = this.obj_clone(target_[k_s], record_set); } } break; } case "function": { result = target_.bind({}); break; } default: { result = target_; } } return result; } /** * 拷贝对象 * @param target 目标 */ public copy(target: object): object { return this.parse(this.stringify(target)); } //请求相关-------------------------------------------- public getReqId(): string { return Date.now() + "_" + Math.ceil(1e3 * Math.random()); } private _url_data: Record | null = null; /**获取链接中传入的某个值*/ public getUrlData(key: string): T | null { if (!this._url_data) { this._url_data = this.parseUrl(); } const value = this._url_data[key]; if (value === undefined) return null; if (typeof value === 'string') { const numberValue = parseFloat(value); if (!isNaN(numberValue)) return (numberValue as unknown) as T; return value as T; } return null; } private parseUrl(): Record { if (!sys.isBrowser || typeof window !== "object" || !window.document) return {}; const url = window.document.location.href; const queryString = url.split("?")[1]; if (!queryString) return {}; return queryString.split("&").reduce>((acc, param) => { const [key, value] = param.split("="); if (key) acc[decodeURIComponent(key)] = value ? decodeURIComponent(value) : ''; return acc; }, {}); } /**获到node的坐标和范围用于平台在对应位置创建按纽*/ public getBtnOp(btnNode: Node): { left: number, top: number, width: number, height: number } { let btnNodeUiTransform = btnNode.getComponent(UITransform); const btnSize = size(btnNodeUiTransform.width + 0, btnNodeUiTransform.height + 0); //let frameWidth = screen.windowSize.width / screen.devicePixelRatio let frameHeight = screen.windowSize.height / screen.devicePixelRatio //const winSize = screen.windowSize; //const designSize = view.getDesignResolutionSize(); //console.log('designSize', designSize); //console.log('winSize:', winSize); //console.log('frameSize:', frameWidth,frameHeight); //适配不同机型来创建微信授权按钮 let rect = btnNodeUiTransform.getBoundingBoxToWorld(); let ratio = screen.devicePixelRatio; let scale = view.getScaleX(); let factor = scale / ratio; let offsetX = 0; let offsetY = 0; let top = frameHeight - (rect.y + rect.height) * factor - offsetY; let left = rect.x * factor + offsetX; const width = btnSize.width * factor; const height = btnSize.height * factor; return { left: left, top: top, width: width, height: height } } /**远程加载图片*/ public async loadImage(url: string): Promise { if (chsdk.get_pf() == chsdk.pf.web) { return await this.loadRemoteSprite(url); } else { const idata = await chsdk.loadImage(url); return this.getSpriteFrame(idata); } } /**cocos加载远程图片*/ public loadRemoteSprite(remoteUrl: string, ext: '.png' | '.jpg' = '.png'): Promise { return new Promise((resolve) => { assetManager.loadRemote(remoteUrl, { ext: ext }, function (err, imageAsset) { const spriteFrame = new SpriteFrame(); const texture = new Texture2D(); texture.image = imageAsset; spriteFrame.texture = texture; resolve(spriteFrame); }); }); } /**远程加载的图片数据转成spriteFrame*/ private getSpriteFrame(img: any): SpriteFrame { if (!img) return null; try { const spriteFrame = new SpriteFrame(); const texture = new Texture2D(); texture.image = img instanceof ImageAsset ? img : new ImageAsset(img); spriteFrame.texture = texture; return spriteFrame; } catch (error) { //ch_log.warn(error); return null; } } } export default ch_util.getInstance();