You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
468 lines
12 KiB
TypeScript
468 lines
12 KiB
TypeScript
const oneMinuteSeconds = 60
|
|
const onehourSeconds = oneMinuteSeconds * 60
|
|
const oneDaySeconds = onehourSeconds * 24
|
|
|
|
let forbiddenWords: string[] = undefined
|
|
|
|
export class Utils {
|
|
|
|
//是否空值
|
|
public static isNull(o: any): boolean {
|
|
let type = Object.prototype.toString.call(o);
|
|
return ("[object Null]" === type || "[object Undefined]" === type);
|
|
}
|
|
|
|
//是否字符串
|
|
public static isString(o: any): boolean {
|
|
return ("[object String]" === Object.prototype.toString.call(o));
|
|
}
|
|
|
|
//是否数字
|
|
public static isNumber(o: any): boolean {
|
|
return ("[object Number]" === Object.prototype.toString.call(o));
|
|
}
|
|
|
|
//是否数组
|
|
public static isArray(o: any): boolean {
|
|
return ("[object Array]" === Object.prototype.toString.call(o));
|
|
}
|
|
|
|
//是否字典
|
|
public static isObject(o: any): boolean {
|
|
return ("[object Object]" === Object.prototype.toString.call(o));
|
|
}
|
|
|
|
//是否方法
|
|
public static isFunction(o: any): boolean {
|
|
return ("[object Function]" === Object.prototype.toString.call(o));
|
|
}
|
|
|
|
//继承
|
|
public static inherit(base: Function, obj: Function) {
|
|
for (let key in base.prototype) {
|
|
obj.prototype[key] = base.prototype[key];
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
//继承
|
|
public static queryUrl(url: string) {
|
|
let querys = {};
|
|
let index = url.indexOf("?")
|
|
cc.log(index)
|
|
if (index >= 0) {
|
|
let strs = url.substr(index + 1).split("&")
|
|
for (let i = 0, len = strs.length; i < len; i++) {
|
|
if (strs[i].indexOf("=") > 0) {
|
|
let params = strs[i].split("=");
|
|
if (params[0].trim() != "") {
|
|
querys[params[0]] = params[1];
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return querys;
|
|
}
|
|
|
|
// 将base64字符串转换成图片
|
|
public static getSpritFrameFromBase64(base64: string): cc.SpriteFrame {
|
|
base64 = "data:image/jpeg;base64," + base64;
|
|
let img = new Image();
|
|
img.src = base64;
|
|
let texture = new cc.Texture2D();
|
|
texture.initWithElement(img);
|
|
texture.handleLoadedTexture();
|
|
return new cc.SpriteFrame(texture);
|
|
}
|
|
|
|
//生成uuid
|
|
public static uuid(length: number) {
|
|
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
|
let uuid = [], i = 0;
|
|
let radix = chars.length;
|
|
|
|
if (length > 0) {
|
|
// Compact form
|
|
for (i = 0; i < length; i++) uuid[i] = chars[0 | Math.random() * radix];
|
|
} else {
|
|
// rfc4122, version 4 form
|
|
let r: number = 0;
|
|
|
|
// rfc4122 requires these characters
|
|
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
|
uuid[14] = '4';
|
|
|
|
// Fill in random data. At i==19 set the high bits of clock sequence as
|
|
// per rfc4122, sec. 4.1.5
|
|
for (i = 0; i < 36; i++) {
|
|
if (!uuid[i]) {
|
|
r = 0 | Math.random() * 16;
|
|
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
|
|
}
|
|
}
|
|
}
|
|
|
|
return uuid.join('');
|
|
}
|
|
|
|
//复制文本
|
|
public static onCopyText(copyText: string): boolean {
|
|
if (cc.sys.isBrowser) {
|
|
let input = document.createElement("input");
|
|
input.setAttribute("readonly", "readonly");
|
|
input.setAttribute("value", copyText);
|
|
|
|
input.style.position = "absolute";
|
|
input.style.left = "-9999px";
|
|
input.style.fontSize = "12pt"; // Prevent zooming on iOS
|
|
|
|
document.body.appendChild(input);
|
|
|
|
input.select();
|
|
input.setSelectionRange(0, 128);
|
|
|
|
let success = false;
|
|
try {
|
|
if (document.execCommand("Copy")) {
|
|
success = true;
|
|
}
|
|
} catch (e) {
|
|
console.log(e)
|
|
}
|
|
document.body.removeChild(input);
|
|
|
|
return success;
|
|
} else {
|
|
// if (Common.OpenFunction.COPYTEXT) {
|
|
// if (cc.sys.os == cc.sys.OS_ANDROID) {
|
|
// jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "JavaCopy", "(Ljava/lang/String;)V", copyText);
|
|
// return true
|
|
// }
|
|
// else if (cc.sys.os == cc.sys.OS_IOS) {
|
|
// let IOS_API = "AppController";
|
|
// jsb.reflection.callStaticMethod(IOS_API, "JavaCopy:", copyText);
|
|
// return true
|
|
// }
|
|
// }
|
|
}
|
|
return false
|
|
}
|
|
|
|
//复制文本
|
|
public static getCopyText(): string {
|
|
let copyText = ""
|
|
|
|
// if (Common.OpenFunction.COPYTEXT) {
|
|
// if (cc.sys.os == cc.sys.OS_ANDROID) {
|
|
// copyText = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getDuplicateContent", "()Ljava/lang/String;");
|
|
// }
|
|
// else if (cc.sys.os == cc.sys.OS_IOS) {
|
|
// let IOS_API = "AppController";
|
|
// copyText = jsb.reflection.callStaticMethod(IOS_API, "getDuplicateContent:", "");
|
|
// }
|
|
// }
|
|
return copyText
|
|
}
|
|
|
|
/**
|
|
* 尋找當前scrollView滑動百分比
|
|
* @param scrollView
|
|
*/
|
|
public static judgeScrollPercent(scrollView: cc.ScrollView) {
|
|
const offset = scrollView.getScrollOffset()
|
|
const maxOffset = scrollView.getMaxScrollOffset()
|
|
const offsetArray = [offset.x, offset.y]
|
|
const maxOffsetArray = [maxOffset.x, maxOffset.y, maxOffset.y]
|
|
const index = maxOffsetArray.indexOf(Math.max(...maxOffsetArray))
|
|
offsetArray[index] = Math.abs(offsetArray[index])
|
|
offsetArray[index] = offsetArray[index] < 0 ? 0 : offsetArray[index]
|
|
offsetArray[index] = offsetArray[index] > maxOffsetArray[index] ? maxOffsetArray[index] : offsetArray[index]
|
|
return offsetArray[index] / maxOffsetArray[index]
|
|
}
|
|
|
|
/**
|
|
* 轉換錢幣
|
|
*/
|
|
public static moneyUnitConvert(money: number) {
|
|
if (money < 1000) {
|
|
return money + ''
|
|
} else {
|
|
return money / 1000 + 'K'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 三位一撇
|
|
*/
|
|
public static numberWithCommas(number: number) {
|
|
let parts = number.toFixed(2).split('.')
|
|
let decimal = parts[1].slice();
|
|
|
|
for (let i = parts[1].length - 1; i >= 0; i--) {
|
|
if (parts[1][i] != '0') {
|
|
break;
|
|
}
|
|
else {
|
|
decimal = decimal.substr(0, i);
|
|
}
|
|
}
|
|
parts[1] = decimal;
|
|
return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (parts[1] ? '.' + parts[1] : '')
|
|
}
|
|
|
|
/**
|
|
* 無條件捨去
|
|
*/
|
|
public static roundDown(number: number) {
|
|
return Number(String(number).split(".")[0])
|
|
}
|
|
|
|
public static deepClone(data: any) {
|
|
if (data === undefined || data === null) {
|
|
return data
|
|
}
|
|
return JSON.parse(JSON.stringify(data || {}))
|
|
}
|
|
|
|
/**
|
|
* 閃爍動畫
|
|
* @param node 閃爍節點
|
|
* @param duration 間隔
|
|
* @param repeat 重複次數(-1為無限)
|
|
* @param callBack 回調函式
|
|
*/
|
|
public static blink(node: cc.Node, duration: number, repeat = 0, endShow: boolean = true, callBack?: Function) {
|
|
// cc.log(`blick duration:${duration} repeat:${repeat}`);
|
|
node.active = true
|
|
cc.Tween.stopAllByTarget(node)
|
|
|
|
node.opacity = 0;
|
|
const show = endShow ? 255 : 0;
|
|
let action = cc.tween()
|
|
.to(duration, { opacity: 0 }, { easing: 'quadIn' })
|
|
.to(duration, { opacity: 255 }, { easing: 'quadOut' })
|
|
|
|
cc.tween(node).repeat(repeat, action).call(() => { node.opacity = show; callBack && callBack() }).start();
|
|
}
|
|
|
|
public static currencyFilter(value: number) {
|
|
if (value < 1000) {
|
|
return `${value}`
|
|
}
|
|
value = value - (value % 100)
|
|
return `${value / 1000}K`
|
|
}
|
|
|
|
public static getCanvasInParent(node: cc.Node): cc.Canvas {
|
|
if (!node) {
|
|
return undefined
|
|
}
|
|
|
|
let canvas = undefined
|
|
let parent = node.parent
|
|
while (!canvas) {
|
|
if (!parent) {
|
|
break
|
|
}
|
|
|
|
canvas = parent.getComponent(cc.Canvas)
|
|
parent = parent.parent
|
|
}
|
|
|
|
return canvas
|
|
}
|
|
|
|
public static clamp(val: number, min: number, max: number): number {
|
|
return val < min ? min : (val > max ? max : val)
|
|
}
|
|
|
|
public static copyString(str: string) {
|
|
const el = document.createElement('textarea')
|
|
el.value = str
|
|
el.setAttribute('readonly', '')
|
|
// el.style.contain = 'strict';
|
|
el.style.position = 'absolute'
|
|
el.style.left = '-9999px'
|
|
el.style.fontSize = '12pt' // Prevent zooming on iOS
|
|
|
|
const selection = getSelection()
|
|
let originalRange = null
|
|
if (selection.rangeCount > 0) {
|
|
originalRange = selection.getRangeAt(0)
|
|
}
|
|
document.body.appendChild(el)
|
|
el.select()
|
|
el.selectionStart = 0
|
|
el.selectionEnd = str.length
|
|
|
|
let success = false
|
|
try {
|
|
success = document.execCommand('copy')
|
|
} catch (err) { }
|
|
|
|
document.body.removeChild(el)
|
|
|
|
if (originalRange) {
|
|
selection.removeAllRanges()
|
|
selection.addRange(originalRange)
|
|
}
|
|
if (success) {
|
|
console.log('复制成功')
|
|
} else {
|
|
console.log('复制失败')
|
|
}
|
|
return success
|
|
}
|
|
|
|
public static setButtonInteractable(button: cc.Button, value: boolean) {
|
|
if (!button) {
|
|
return
|
|
}
|
|
|
|
button.interactable = value
|
|
}
|
|
|
|
public static changeNodeParent(node, parent) {
|
|
if (!node) {
|
|
cc.error("changeNodeParent node is null");
|
|
return;
|
|
}
|
|
|
|
if (!parent) {
|
|
cc.error("changeNodeParent parent is null");
|
|
return;
|
|
}
|
|
|
|
let pos = node.parent.convertToWorldSpaceAR(node.getPosition());
|
|
let changePos = parent.convertToNodeSpaceAR(pos);
|
|
node.parent = parent;
|
|
node.setPosition(changePos);
|
|
}
|
|
|
|
public static tweenNumberLabel(label: cc.Label, num: number, suffix: string = '') {
|
|
const currentNum = Number(label.string.replace(/,/g, '').replace(suffix, ''))
|
|
if (!Utils.isNumber(currentNum)) {
|
|
console.warn('label is not number:', label.string)
|
|
return
|
|
}
|
|
if (currentNum >= num) {
|
|
label.string = Utils.numberWithCommas(num) + suffix
|
|
return
|
|
}
|
|
const plusNum = num - currentNum
|
|
const betweenTime = 0.01
|
|
const count = 80
|
|
let currentCount = 0
|
|
label.unscheduleAllCallbacks()
|
|
label.schedule(
|
|
() => {
|
|
if (!label) {
|
|
return
|
|
}
|
|
currentCount += 1
|
|
label.string = Utils.numberWithCommas(Math.round(currentNum + (plusNum / count) * currentCount)) + suffix
|
|
if (currentCount === count) {
|
|
label.string = Utils.numberWithCommas(num) + suffix
|
|
}
|
|
},
|
|
betweenTime,
|
|
count - 1
|
|
)
|
|
}
|
|
|
|
public static tweenSpriteFillrange(sprite: cc.Sprite, percent: number) {
|
|
// cc.log("tweenSpriteFillrange ", percent)
|
|
let changeTotal = percent - sprite.fillRange;
|
|
const count = 80;
|
|
const betweenTime = 0.01
|
|
let per = changeTotal / count;
|
|
let curRange = sprite.fillRange;
|
|
sprite.unscheduleAllCallbacks();
|
|
sprite.schedule(() => {
|
|
curRange += per;
|
|
sprite.fillRange = curRange;
|
|
}, betweenTime, count - 1);
|
|
}
|
|
|
|
// 計算字符長度 (英文數字當成1 其他當成2)
|
|
public static countMultiLangStrLength(str: string): number {
|
|
const originalSize = str.length
|
|
const digitNLetter = str.replace(/[^a-zA-Z0-9]/g, '')
|
|
const englishSize = digitNLetter.length
|
|
const otherLength = (originalSize - digitNLetter.length) * 2
|
|
return englishSize + otherLength
|
|
}
|
|
|
|
public static formatNickname(str: string, maxLen = 6) {
|
|
let len = Utils.countMultiLangStrLength(str);
|
|
let subLen = len;
|
|
while (subLen > maxLen) {
|
|
str = str.substr(0, str.length - 1);
|
|
subLen = Utils.countMultiLangStrLength(str);
|
|
}
|
|
|
|
return len > 6 ? (str + "...") : str;
|
|
}
|
|
|
|
/**
|
|
* 數字換行(奇數上排數字大於下排, 偶數對半)
|
|
* @param numStr 欲轉換數字
|
|
* @param limitNum 幾位後要換行
|
|
*/
|
|
|
|
public static convertChipStr(numStr: string, limitNum: number = 3) {
|
|
const len = numStr.length
|
|
if (len > limitNum) {
|
|
const sliceLen = Math.ceil(len * 0.5)
|
|
return `${numStr.slice(0, sliceLen)}\n${numStr.slice(sliceLen)}`
|
|
} else {
|
|
return numStr
|
|
}
|
|
}
|
|
|
|
/** 發送訊息提示 */
|
|
public static showSendLog(eventName: string, message?: any) {
|
|
if (CC_DEBUG) {
|
|
message = message || {};
|
|
const time = this.convertTimestamp(new Date().getTime());
|
|
let data = JSON.parse(JSON.stringify(message)); // Deep Copy
|
|
console.log("%s %c %s", time, "background: Green; color: White;", "發送 " + eventName + " ", data);
|
|
}
|
|
}
|
|
|
|
/** 回傳訊息提示 */
|
|
public static showResponseLog(eventName: string, message?: any) {
|
|
if (CC_DEBUG) {
|
|
message = message || {};
|
|
const time = this.convertTimestamp(new Date().getTime());
|
|
let data = JSON.parse(JSON.stringify(message)); // Deep Copy
|
|
console.log("%s %c %s", time, "background: Green; color: White;", "回應 " + eventName + " ", data);
|
|
}
|
|
}
|
|
|
|
/** 廣播訊息提示 */
|
|
public static showPushLog(eventName: string, message: any) {
|
|
if (CC_DEBUG) {
|
|
message = message || {};
|
|
const time = this.convertTimestamp(new Date().getTime());
|
|
let data = JSON.parse(JSON.stringify(message)); // Deep Copy
|
|
console.log("%s %c %s", time, "background: Blue; color: White;", "廣播 " + eventName + " ", data);
|
|
}
|
|
}
|
|
|
|
private static convertTimestamp(value: number): string {
|
|
const t = new Date(value);
|
|
// const yyyy = t.getFullYear();
|
|
// const MM = t.getMonth() < 9 ? "0" + (t.getMonth()+1):t.getMonth()+1;
|
|
// const DD = t.getDate() < 10 ? "0" + t.getDate() : t.getDate();
|
|
const hh = t.getHours() < 10 ? "0" + t.getHours() : t.getHours();
|
|
const mm = t.getMinutes() < 10 ? "0" + t.getMinutes() : t.getMinutes()
|
|
const ss = t.getSeconds() < 10 ? "0" + t.getSeconds() : t.getSeconds()
|
|
return `${hh}:${mm}:${ss}`;
|
|
}
|
|
}
|
|
|
|
|