super-hero/assets/cc-common/cc-util/UmUtil.ts

754 lines
24 KiB
TypeScript
Raw Normal View History

2024-05-08 04:03:33 -07:00
import * as cc from "cc";
import { Vec2 } from "cc";
import { Color } from "cc";
import { _decorator, ITweenOption, Node, sp, Tween, tween, UIOpacity, UITransform, Vec3 } from "cc";
const { ccclass, property } = _decorator;
declare const pako: any;
@ccclass("UmUtil")
export class UmUtil {
/**
* !#zh object
*/
public static clone(sObj: any) {
if (sObj === null || typeof sObj !== "object") {
return sObj;
}
let s: any = {};
if (sObj.constructor === Array) {
s = [];
}
for (const i in sObj) {
if (sObj.hasOwnProperty(i)) {
s[i] = this.clone(sObj[i]);
}
}
return s;
}
/**
* object
*/
public static objectToArray(srcObj: any) {
const resultArr = [];
// to array
for (let key in srcObj) {
if (!srcObj.hasOwnProperty(key)) {
continue;
}
resultArr.push(srcObj[key]);
}
return resultArr;
}
/**
* !#zh object
*/
public static arrayToObject(srcObj: any, objectKey: any) {
const resultObj: any = {};
// to object
for (let key in srcObj) {
if (!srcObj.hasOwnProperty(key) || !srcObj[key][objectKey]) {
continue;
}
resultObj[srcObj[key][objectKey]] = srcObj[key];
}
return resultObj;
}
// 根据权重,计算随机内容
public static getWeightRandIndex(weightArr: any, totalWeight: number) {
const randWeight = Math.floor(Math.random() * totalWeight);
let sum = 0;
let weightIndex = 0;
for (weightIndex; weightIndex < weightArr.length; weightIndex++) {
sum += weightArr[weightIndex];
if (randWeight < sum) {
break;
}
}
return weightIndex;
}
/**
* nm
* @param {Number} n
* @param {Number} m
* @returns {Array} array
*/
public static getRandomNFromM(n: number, m: number) {
const array: number[] = [];
let intRd = 0;
let count = 0;
while (count < m) {
if (count >= n + 1) {
break;
}
intRd = this.getRandomInt(0, n);
let flag = 0;
for (let i = 0; i < count; i++) {
if (array[i] === intRd) {
flag = 1;
break;
}
}
if (flag === 0) {
array[count] = intRd;
count++;
}
}
return array;
}
public static getRandomInt(min: number, max: number) {
const r = Math.random();
const rr = r * (max - min + 1) + min;
return Math.floor(rr);
}
public static getStringLength(render: string) {
const strArr = render;
let len = 0;
for (let i = 0, n = strArr.length; i < n; i++) {
const val = strArr.charCodeAt(i);
if (val <= 255) {
len = len + 1;
}
else {
len = len + 2;
}
}
return Math.ceil(len / 2);
}
/**
* Objectundefinedfalse
* @param obj
*/
public static isEmptyObject(obj: any) {
let result = true;
if (obj && obj.constructor === Object) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result = false;
break;
}
}
}
else {
result = false;
}
return result;
}
public static formatNum(num: number) {
// 0 和负数均返回 NaN。特殊处理。
if (num <= 0) {
return '0';
}
const k = 1000;
const sizes = ['', '', 'K', 'M', 'B'];
const i = Math.round(Math.log(num) / Math.log(k));
return parseInt((num / (Math.pow(k, i - 1 < 0 ? 0 : i - 1))).toString(), 10) + sizes[i];
}
public static formatMoneyWithFraction(num: number, fraction?: number) {
return num.toFixed(fraction).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
/**
*
* @param {Object|Number} dateValue todo MessageCenter pve Date
* @returns {boolean}
*/
public static isNewDay(dateValue: any) {
// todo是否需要判断时区
const oldDate = new Date(dateValue);
const curDate = new Date();
const oldYear = oldDate.getFullYear();
const oldMonth = oldDate.getMonth();
const oldDay = oldDate.getDate();
const curYear = curDate.getFullYear();
const curMonth = curDate.getMonth();
const curDay = curDate.getDate();
if (curYear > oldYear) {
return true;
}
else {
if (curMonth > oldMonth) {
return true;
}
else {
if (curDay > oldDay) {
return true;
}
}
}
return false;
}
public static getPropertyCount(o: Object) {
let n, count = 0;
for (n in o) {
if (o.hasOwnProperty(n)) {
count++;
}
}
return count;
}
/**
* arraydiff
* @param array
* @param diff
*/
public static difference(array: any, diff: any) {
const result: number[] = [];
if (array.constructor !== Array || diff.constructor !== Array) {
return result;
}
const length = array.length;
for (let i = 0; i < length; i++) {
if (diff.indexOf(array[i]) === -1) {
result.push(array[i]);
}
}
return result;
}
// 模拟传msg的uuid
public static simulationUUID() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
public static trim(str: string) {
return str.replace(/(^\s*)|(\s*$)/g, "");
}
/**
*
* @param {String|Number} start
* @param {String|Number} end
*/
public static isNowValid(start: string | number, end: string | number) {
const startTime = new Date(start);
const endTime = new Date(end);
let result = false;
if (startTime.getDate() + '' !== 'NaN' && endTime.getDate() + '' !== 'NaN') {
const curDate = new Date();
result = curDate < endTime && curDate > startTime;
}
return result;
}
public static getDeltaDays(start: string | number, end: string | number) {
const startData = new Date(start);
const endData = new Date(end);
const startYear = startData.getFullYear();
const startMonth = startData.getMonth() + 1;
const startDate = startData.getDate();
const endYear = endData.getFullYear();
const endMonth = endData.getMonth() + 1;
const endDate = endData.getDate();
start = new Date(startYear + '/' + startMonth + '/' + startDate + ' GMT+0800').getTime();
end = new Date(endYear + '/' + endMonth + '/' + endDate + ' GMT+0800').getTime();
const deltaTime = end - start;
return Math.floor(deltaTime / (24 * 60 * 60 * 1000));
}
public static getMin(array: any) {
let result = 0;
if (array.constructor === Array) {
const length = array.length;
for (let i = 0; i < length; i++) {
if (i === 0) {
result = Number(array[0]);
}
else {
result = result > Number(array[i]) ? Number(array[i]) : result;
}
}
}
return result;
}
public static formatTwoDigits(time: number) {
return (Array(2).join('0') + time).slice(-2);
}
public static formatDate(date: Date, fmt: string) {
const o: { [name: string]: number } = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
for (const k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (`${o[k]}`) : ((`00${o[k]}`).substr(("" + o[k]).length)));
return fmt;
}
/**
*
*/
public static getDay(time: number, splitChar: string = '-') {
const date = new Date(time);
return date.getDate() + splitChar + (date.getMonth() + 1) + splitChar + date.getFullYear();
}
public static getTime(): number
{
return (new Date()).getTime();
}
/**
* 10000 10K 10000K 10M
*/
public static formatMoney(money: number) {
const arrUnit = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'B', 'N', 'D'];
let strValue = '';
for (let idx = 0; idx < arrUnit.length; idx++) {
if (money >= 10000) {
money /= 1000;
}
else {
strValue = Math.floor(money) + arrUnit[idx];
break;
}
}
if (strValue === '') {
strValue = Math.floor(money) + 'U'; //超过最大值就加个U
}
return strValue;
}
/**
* HH:MM:SS
* @param {Number} leftSec
*/
public static formatTimeForSecond(leftSec: number) {
let timeStr = '';
const sec = leftSec % 60;
let leftMin = Math.floor(leftSec / 60);
leftMin = leftMin < 0 ? 0 : leftMin;
const hour = Math.floor(leftMin / 60);
const min = leftMin % 60;
if (hour > 0) {
timeStr += hour > 9 ? hour.toString() : '0' + hour;
timeStr += ':';
}
timeStr += min > 9 ? min.toString() : '0' + min;
timeStr += ':';
timeStr += sec > 9 ? sec.toString() : '0' + sec;
return timeStr;
}
/**
* HH:MM:SS
*
* @param {Number} ms
*/
public static formatTimeForMillisecond(ms: number) {
let second = Math.floor(ms / 1000 % 60);
let minute = Math.floor(ms / 1000 / 60 % 60);
let hour = Math.floor(ms / 1000 / 60 / 60);
let strSecond = second < 10 ? '0' + second : second;
let strMinute = minute < 10 ? '0' + minute : minute;
let strHour = hour < 10 ? '0' + hour : hour;
return `${strSecond}:${strMinute}:${strHour}`;
}
/**
* TODO pako使
*
* @param {String} str
*/
public static zip(str: string) {
const binaryString = pako.gzip(encodeURIComponent(str), { to: 'string' });
// @ts-ignore
return this.base64encode(binaryString);
}
public static rand(arr: any) {
let arrClone = this.clone(arr);
// 首先从最大的数开始遍历,之后递减
for (let i = arrClone.length - 1; i >= 0; i--) {
// 随机索引值randomIndex是从0-arrClone.length中随机抽取的
const randomIndex = Math.floor(Math.random() * (i + 1));
// 下面三句相当于把从数组中随机抽取到的值与当前遍历的值互换位置
const itemIndex = arrClone[randomIndex];
arrClone[randomIndex] = arrClone[i];
arrClone[i] = itemIndex;
}
// 每一次的遍历都相当于把从数组中随机抽取不重复的一个元素放到数组的最后面索引顺序为len-1,len-2,len-3......0
return arrClone;
}
public static randRange(min: any, max: any) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
public static getPostionNodeInOtherNode(spaceNode: any, targetNode: any) {
if (targetNode.parent == null) {
return null;
}
let pos = new Vec3(0, 0, 0);
const targetNodeComponent = targetNode.parent.getComponent(UITransform);
const spaceNodeComponent = spaceNode.getComponent(UITransform);
if (!targetNodeComponent) {
targetNode.parent.addComponent(UITransform);
}
if (!spaceNodeComponent) {
spaceNode.addComponent(UITransform);
}
pos = targetNodeComponent.convertToWorldSpaceAR(targetNode.getPosition());
return spaceNodeComponent ? spaceNodeComponent.convertToNodeSpaceAR(pos) : pos;
}
public static getPointInNodeFromWorldPoint(worldPoint: Vec3, node: Node) {
return node.getComponent(UITransform)?.convertToNodeSpaceAR(worldPoint);
}
public static validURL(str: string) {
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
return !!pattern.test(str);
}
public static deepEqual(object1: any, object2: any) {
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
const val1 = object1[key];
const val2 = object2[key];
const areObjects = this.isObject(val1) && this.isObject(val2);
if (
areObjects && !this.deepEqual(val1, val2) ||
!areObjects && val1 !== val2
) {
return false;
}
}
return true;
}
public static isObject(object: any) {
return object != null && typeof object === 'object';
}
public static getKeyObject(obj: any, value: any) {
let result: string = "";
for (let [key, val] of Object.entries(obj)) {
if (value === val) {
result = key;
break;
}
}
return result;
}
public static getHighestSiblingIndexOfChild(parentNode: Node): number {
let highestSiblingIndex: number = 0;
parentNode.children.forEach((child: Node, index: number) => {
const siblingIndex = child.getSiblingIndex();
if (highestSiblingIndex < siblingIndex) {
highestSiblingIndex = siblingIndex;
}
});
return highestSiblingIndex;
}
public static fadeTo(target: Node, duration: number, opacity: number, options?: ITweenOption, callback?: Function): Tween<object> {
let uiOpacity = target.getComponent(UIOpacity)!;
if (uiOpacity === null) uiOpacity = target.addComponent(UIOpacity);
let spine: sp.Skeleton = target.getComponent(sp.Skeleton)!;
options = options || {};
if (spine) {
if (options.onUpdate) {
let _onUpdate = options.onUpdate;
options.onUpdate = function () {
UmUtil.setAlphaSpine(spine, uiOpacity.opacity);
_onUpdate && _onUpdate();
}
}
else {
options.onUpdate = function () {
UmUtil.setAlphaSpine(spine, uiOpacity.opacity);
}
}
}
let tweenFade = tween(uiOpacity);
tweenFade.to(duration, { opacity }, options).start();
(target as any).tweenFade = tweenFade;
return tweenFade;
}
public static fadeIn(target: Node, duration: number, options?: ITweenOption): Tween<Node> {
return UmUtil.fadeTo(target, duration, 255, options);
}
public static fadeOut(target: Node, duration: number, options?: ITweenOption): Tween<Node> {
return UmUtil.fadeTo(target, duration, 0, options);
}
public static uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
public static getWindowSize(): cc.Size {
return cc.screen.windowSize;
}
public static getCanvasSize(): cc.Size {
const viewSize = cc.screen.windowSize;
const designSize = cc.view.getDesignResolutionSize();
let windowWidth = viewSize.width;
let windowHeight = viewSize.height;
let windowRatio = windowWidth * 1.0 / windowHeight;
const designRatio = designSize.width * 1.0 / designSize.height;
let height = designSize.height;
if (windowRatio <= designRatio) {
// let cHeight = Math.floor(designSize.width / windowRatio);
height = designSize.width / viewSize.width * viewSize.height;
}
cc.log("getCanvasSize ==> ", designSize.width, height);
return new cc.Size(designSize.width, height);
}
public static multiplicationExact(numb1: number, numb2: number) {
let digit1 = Number(numb1.toString().split('.')[1]?.length);
if (Number.isNaN(digit1)) digit1 = 0;
let digit2 = Number(numb2.toString().split('.')[1]?.length);
if (Number.isNaN(digit2)) digit2 = 0;
let maxDigit = digit1 + digit2;
for (let i = 0; i < 7; i++) {
let factor = Math.pow(10, i);
let result = ((numb1 / factor) * (numb2 / factor)) * factor * factor;
let digit_check = Number(result.toString().split('.')[1]?.length);
if (Number.isNaN(digit_check) || Number(digit_check) <= maxDigit) {
// cc.log(" multipl1 ===> digit = ", digit_check, " | pow = 10^", i);
return result;
}
}
for (let i = 0; i < 7; i++) {
let factor = Math.pow(10, i);
let result = ((numb1 / factor) * (numb2 / factor)) * Math.pow(factor, 2);
let digit_check = Number(result.toString().split('.')[1]?.length);
if (Number.isNaN(digit_check) || Number(digit_check) <= maxDigit) {
// cc.log(" multipl2 ===> digit_check = ", digit_check, " | pow = 10^", i);
return result;
}
}
// cc.log("RESULT ==> ", result);
return numb1 * numb2;
}
public static setLabelSubStringByMaxWidth(label: cc.Label, maxWidth: number) {
label.updateRenderData();
let transform = label.getComponent(UITransform)!;
if (transform.width > maxWidth) {
while (transform.width > maxWidth) {
label.string = label.string.slice(0, -1);
label.updateRenderData();
}
label.string += "...";
}
}
public static PlusExact(numb1: number, numb2: number) {
let digit1 = Number(numb1.toString().split('.')[1]?.length);
if (Number.isNaN(digit1)) digit1 = 0;
let digit2 = Number(numb2.toString().split('.')[1]?.length);
if (Number.isNaN(digit2)) digit2 = 0;
let maxDigit = Math.max(digit1, digit2);
for (let i = 0; i < 7; i++) {
let factor = Math.pow(10, i);
let result = ((numb1 / factor) + (numb2 / factor)) * factor * factor;
let digit_check = Number(result.toString().split('.')[1]?.length);
if (Number.isNaN(digit_check) || Number(digit_check) <= maxDigit) {
// cc.log(" multipl1 ===> digit = ", digit_check, " | pow = 10^", i);
return result;
}
}
for (let i = 0; i < 7; i++) {
let factor = Math.pow(10, i);
let result = ((numb1 / factor) + (numb2 / factor)) * Math.pow(factor, 2);
let digit_check = Number(result.toString().split('.')[1]?.length);
if (Number.isNaN(digit_check) || Number(digit_check) <= maxDigit) {
// cc.log(" multipl2 ===> digit_check = ", digit_check, " | pow = 10^", i);
return result;
}
}
// cc.log("RESULT ==> ", result);
return numb1 + numb2;
}
public static setAlphaSpine(spine: sp.Skeleton, alpha: number) {
let color: Color = Color.clone(spine.color);
color.a = alpha;
spine.color = color;
}
public static moveTo(obj: Node, pointTo: Vec3, duration: number, delayTime?: number, callback?: Function, tag = UmUtil.TWEEN_TAG) {
if (!obj) return;
tween(obj).delay(delayTime).to(duration, { position: pointTo }).call(() => callback?.()).tag(tag).start();
}
public static worldMoveTo(obj: Node, worldPointTo: Vec3, duration: number, delayTime?: number, callback?: Function, tag = UmUtil.TWEEN_TAG) {
if (!obj) return;
tween(obj).delay(delayTime).to(duration, { worldPosition: worldPointTo }).call(() => callback?.()).tag(tag).start();
}
public static scaleTo(obj: Node, scaleTo: Vec3, duration: number, delayTime?: number, callback?: Function, tag = UmUtil.TWEEN_TAG) {
if (!obj) return;
tween(obj).delay(delayTime).to(duration, { scale: scaleTo }).call(() => callback?.()).tag(tag).start();
}
public static delay(obj: Node, delayTime: number, callback: Function, tag = UmUtil.TWEEN_TAG) {
tween(obj).delay(delayTime).call(() => {
if (obj?.active) {
callback?.();
}
}).tag(tag).start();
}
public static rotateBy(obj: Node, angle: number, duration: number, delayTime?: number, callback?: Function, tag = UmUtil.TWEEN_TAG) {
if (!obj) return;
tween(obj).delay(delayTime).by(duration, { angle: angle }).call(() => callback?.()).tag(tag).start();
}
public static tweenValue(from, to, duration, updateCallback = null, completeCallback = null)
{
const _target = { value: from };
var tweenValue = tween(_target)
.to(duration, { value: to }, {
'onStart': () => {
},
'onUpdate': () => {
updateCallback?.(_target.value);
},
'onComplete': () => {
completeCallback?.();
}
});
tweenValue.start();
return tweenValue;
}
public static TWEEN_TAG = 2003;
public static stopAllTweenTarget(obj: Node)
{
Tween.stopAllByTarget(obj);
}
public static stopAllTweenTag(tag: number) {
Tween.stopAllByTag(tag);
}
public static plusTwoVector3(a: Vec3, b: Vec3)
{
var result = new Vec3();
Vec3.add(result, a, b);
return result;
}
public static subtractTwoVector3(a: Vec3, b: Vec3) {
var result = new Vec3();
Vec3.subtract(result, a, b);
return result;
}
public static scaleVector3(a: Vec3, b: number) {
return new Vec3(a.x * b, a.y * b, a.z * b);
}
// public static subtractTwoVector3(a: Vec3, b: Vec3) {
// var result = new Vec3();
// Vec3.subtract(result, a, b);
// return result;
// }
}