namespace vv { /**全局消息注册分发 */ export let Notifi = new cc.EventTarget(); /**存储本地数据 */ export function saveData(name: string, data: any) { data = JSON.stringify(data) cc.log("本地存储:", name, data) cc.sys.localStorage.setItem(name, data); } /**读取本地数据 */ export function readData(name: string) { let data = cc.sys.localStorage.getItem(name) data = JSON.parse(data); cc.log("本地读取:", name, data) return data } export let lang = lang_(); export function lang_(): string { let str = cc.sys.localStorage.getItem("language"); if (str == "" || str == null) str = "en"; return str; }; /**找到子节点 @param nodeName 子节点名称 @param parentNode 开始寻找的父节点 */ export function findChildNode(nodeName: string, parentNode: cc.Node) { let node: cc.Node = null let nodes: cc.Node[] = [] let fun = (parentNode: cc.Node) => { for (let i of parentNode.children) { if (i.name == nodeName) { nodes.push(i) if (nodes.length > 1) { //cc.warn("至少存在2个同名子节点:", nodes, nodeName, parentNode.name) return node } } if (i.childrenCount > 0) { fun(i) } } } fun(parentNode) switch (nodes.length) { case 0: //cc.warn("找不到子节点:", nodeName, parentNode.name) return null; default: return nodes[0]; } } /** * 加载图片 * @param url 图片地址(网图不加png后缀,本地需要) * @param spriteNode 需要改变纹理的节点 * @param isNet 默认false:本地资源, true:是网图 */ export function loadTexture(url: string, spriteNode: cc.Node | cc.Sprite, isNet?: boolean) { if (spriteNode == null) return spriteNode.getComponent(cc.Sprite).spriteFrame = null if (url == "" || url == null) return cc.log("url is null"); if (isNet == null || !isNet) { cc.loader.loadRes(url, cc.SpriteFrame, (error, texture) => { if (error) { cc.warn("图片加载失败!path:", url) return } let sp = texture if (!spriteNode.isValid) return; if (spriteNode instanceof cc.Node) { spriteNode.getComponent(cc.Sprite).spriteFrame = sp } else { spriteNode.spriteFrame = sp } }) } else { cc.loader.load(url, (error, texture) => { if (error) return error let sp = new cc.SpriteFrame(texture) if (!spriteNode.isValid) return; if (spriteNode instanceof cc.Node) { spriteNode.getComponent(cc.Sprite).spriteFrame = sp } else { spriteNode.spriteFrame = sp } }) } } /** * 添加点击事件 * 回调必须要lambda表达式或者bind(this) * @param target 添加点击的节点 * @param cb 回调方法 * @param bindNode 绑定脚本 */ export function addBtnEvent(target: cc.Node, cb: Function, bindNode: any, clickAudio = true) { let btn: cc.Button = target.getComponent(cc.Button); if (!btn) btn = target.addComponent(cc.Button); btn.clickEvents = []; target.on("click", (...arg) => { // if (clickAudio) //vv.playAudio("ui_click"); cb?.(...arg); }, bindNode); } export function deleteBtnEvent(target: cc.Node, bindNode: any, clickAudio = true) { let btn: cc.Button = target.getComponent(cc.Button); if (!btn) btn = target.addComponent(cc.Button); btn.clickEvents = []; target.targetOff(bindNode) } /** * 数字跳动 * @param startNum 起始值 * @param originNum 目标值 * @param go 数字节点 * @param time 跳动时间 */ export function numberAnim(startNum: number, endNum: number, go: cc.Node, str: string = "", time: number = 0.6) { let originNum = (endNum - startNum) * 100; let obj: any = {}; obj.num = originNum; let tempNum = 0; let ac = cc.tween(obj) .to(time, { num: 0 }, { progress: (start, end, current, t) => { tempNum = Math.ceil((start - end) * t); go.getComponent(cc.Label).string = str + vv.goldFormat((Number(Number(startNum) + Number(((tempNum) / 100).toFixed(2))).toFixed(2))); return start + (start - end) * t; } }) .call(() => { go.getComponent(cc.Label).string = str + vv.goldFormat(Number(endNum).toFixed(2)); }) .start(); return ac; } /** * 将数字格式转换成 100.000,00 的格式 * @param num 数字或字符串类型的数 * @param isInt 整数是否保留.00 * @returns */ export function goldFormat(num, isInt = false) { if (typeof (num) == "string") num = Number(num); let fushu = false; if (num < 0) { fushu = true; num = Math.abs(num); } if (isInt) { num = num.toString(); if (num.indexOf(".") != -1) { num = num.split(".")[0]; cc.warn("当前传入的不是正数"); } let str = ""; let zheng = ""; let idx = 0; for (let i = num.length - 1; i > -1; i--) { str = num[i] + str; idx++; if (idx % 3 == 0 || i == 0) { if (zheng != "") zheng = str + "." + zheng; else zheng = str + zheng; str = ""; } } return fushu ? "-" + zheng : zheng; } num = num.toFixed(2); let arr = num.split("."); let dian = arr.length == 1 ? "00" : arr[1]; if (Number(dian) < 10 && dian.length == 1) dian = "0" + dian; let str = ""; let zheng = ""; let idx = 0; for (let i = arr[0].length - 1; i > -1; i--) { str = arr[0][i] + str; idx++; if (idx % 3 == 0 || i == 0) { if (zheng != "") zheng = str + "." + zheng; else zheng = str + zheng; str = ""; } } return fushu ? ("-" + zheng + "," + dian) : (zheng + "," + dian); } /** * 分割网址中的参数 * @param url 网址 * @returns */ export function getUrlData(url: string): any { let arr = url.split("?"); if (arr.length == 1) { return null } let arr1 = arr[1].split("&"); let data = {}; arr1.forEach(v => { let temp = v.split('='); if (!temp[1] || data[temp[0]]) { } else data[temp[0]] = temp[1]; }); return data; } /**加载预制体并适配 适配仅限个别预制体 */ export function loadPrefab(str, parent = null, cb = null, isactive = true) { return new Promise((resolve, reject) => { cc.resources.load("Prefab/" + str, (err, res) => { if (err) { reject(err); return cc.warn(err); } let can = cc.find("Canvas"); let ch = cc.instantiate(res); let arr = str.split("/"); ch.name = arr[arr.length - 1]; ch.active = isactive; if (parent == null) ch.parent = can; else ch.parent = parent; if (cb != null && typeof (cb) == 'function') cb(ch); resolve(ch); }) }) } /**预加载场景 */ export function preLoadScene(sceneName, onProgressCB = null) { return new Promise((resolve, reject) => { cc.director.preloadScene(sceneName, (completedCount: number, totalCount: number, item: any) => { onProgressCB && onProgressCB(completedCount, totalCount); }, (err) => { if (err) { reject(err); return; } cc.log(`场景 ${sceneName} 预加载完成`) resolve(sceneName); }) }); } /**预加载场景 */ export function loadScene(sceneName, onProgressCB = null) { return new Promise((resolve, reject) => { cc.director.loadScene(sceneName, (err) => { if (err) { reject(err); return; } cc.log(`场景 ${sceneName} 加载完成`) resolve(sceneName); onProgressCB?.() }) }); } /**时间戳转换成时间格式 @param format 格式,比如:"2019.6.3" "2018-11-27" "11月7日" "13:05:45:585" @param time 时间戳[13位](兼容10位 默认当前时间) @param bitZero 是否补零(只针对月、日) 默认不补零 */ export function timeToTime(format: string, time?: number, bitZero: boolean = false) { if (time == null) time = Date.now() if (time < 100000000000) time = time * 1000 let newTime = new Date(time) let str = "" if (format.includes(" ")) { cc.warn("该时间字符串模版未实现解析:", format) return str } if (format.indexOf(":") == -1) { //年月日 let year = String(newTime.getFullYear()) let month = String(newTime.getMonth() + 1) let day = String(newTime.getDate()) if (bitZero) { if (month.length == 1) month = "0" + month if (day.length == 1) day = "0" + day } let m = "" if (format.indexOf(".") > 0) m = "." else if (format.indexOf("-") > 0) m = "-" else if (format.indexOf("/") > 0) m = "/" if (m != "") { let num = 0 for (let i = 0; i < format.length; i++) { if (format[i] == m) num++ } if (num == 2) { //年月日 str = year + m + month + m + day } else if (num == 1) { //年月或月日 if (format.length < 6) { //月日 str = month + m + day } else { //年月 str = year + m + month } } } else { if (format.includes("年") && format.includes("日")) { //年月日 str = year + "年" + month + "月" + day + "日" } else if (format.includes("年")) { //年月 str = year + "年" + month + "月" } else if (format.includes("日")) { //月日 str = month + "月" + day + "日" } } } else { let f = format.split(':') let hour = String(newTime.getHours()) let minute = String(newTime.getMinutes()) let second = String(newTime.getSeconds()) let millisecond = String(newTime.getMilliseconds()) if (hour.length == 1) hour = "0" + hour if (minute.length == 1) minute = "0" + minute if (second.length == 1) second = "0" + second while (millisecond.length < 3) millisecond = "0" + millisecond if (f.length == 4) { //小时:分:秒:毫秒 str = hour + ":" + minute + ":" + second + ":" + millisecond } else if (f.length == 3) { if (f[2].length > 2 || +f[0] > 24) { //分:秒:毫秒 str = minute + ":" + second + ":" + millisecond } else { //小时:分:秒 str = hour + ":" + minute + ":" + second } } else if (f.length == 2) { if (+f[0] > 24) { //分:秒 str = minute + ":" + second } else { //小时:分 str = hour + ":" + minute } } } if (str == "") cc.warn("该时间字符串模版未实现解析:", format) return str } /** 00:00:00 */ export function timeToTime2(time?: number) { if (time == null) time = Date.now() if (time < 100000000000) time = time * 1000 let newTime = new Date(time) let str = "" let hour = String(newTime.getHours()) let minute = String(newTime.getMinutes()) let second = String(newTime.getSeconds()) if (hour.length == 1) hour = "0" + hour if (minute.length == 1) minute = "0" + minute if (second.length == 1) second = "0" + second str = hour + ":" + minute + ":" + second; cc.log(hour, minute, second) cc.log(str) return str } /** 00:00:00 */ export function timeToTime3(time?: number) { let str = ""; let hour: any = Math.floor(time / 3600); let less: any = time - 3600 * hour; let minute: any = Math.floor(less / 60); less = less - 60 * minute; let second: any = less; if (hour < 10) hour = "0" + hour; if (minute < 10) minute = "0" + minute; if (second < 10) second = "0" + second; str = hour + ":" + minute + ":" + second; return str } //加载resources下文件 export function loadRes(url, type, completeCallback?, progressCallback?) { var extname = cc.path.extname(url); if (extname) { url = url.slice(0, - extname.length); } cc.resources.load(url, type, progressCallback, (err, asset: cc.Asset) => { if (err) { console.error("加载失败", url, "\n", err); return; } completeCallback(asset); }); } /**子节点转换子节点坐标 */ export function nodePosToNodePos(node_1: cc.Node, node_2: cc.Node) { let wPos = this.nodePosToWord(node_1); let nPos = this.nodePosToNode(node_2); return nPos; } /**转世界坐标 */ export function nodePosToWord(node: cc.Node) { return node.parent.convertToWorldSpaceAR(node.position); } /**将世界坐标转节点坐标 */ export function nodePosToNode(pos: cc.Vec3, node: cc.Node) { return node.convertToNodeSpaceAR(pos); } /**限制小数点后位数,大于5位限制5,小于5显示正常,最少保留2位 */ export function limtStr(number, limit = 5) { let str = number.toString(); let arr = str.split("."); if (arr.length > 1 && arr[1].length > 2) { if (arr[1].length > 5) return number.toFixed(limit); else return number.toFixed(arr[1].length); } return number.toFixed(2); } export function maskString(str: string): string { const length = str.length; if (length === 0) { // 如果是空字符串,返回 "***" return '***'; } else if (length === 1) { // 如果长度为1,保留该字符前后加上“***” return str + '***'; } else if (length === 2) { // 如果长度为2,保留前1和后1,中间加上“***” return str.charAt(0) + '***' + str.charAt(1); } else if (length < 6) { // 如果长度小于6,保留前2位和后2位 return str.slice(0, 2) + '***' + str.slice(-2); } else { // 如果长度大于或等于6,保留前3位和后3位 return str.slice(0, 3) + '***' + str.slice(-3); } } export function webCopyString(copyStr) { const el = document.createElement('textarea'); el.value = copyStr; // Prevent keyboard from showing on mobile 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; if (selection.rangeCount > 0) { originalRange = selection.getRangeAt(0); } document.body.appendChild(el); el.select(); // Explicit selection workaround for iOS el.selectionStart = 0; el.selectionEnd = copyStr.length; let success = false; try { success = document.execCommand('copy'); } catch (err) { } document.body.removeChild(el); if (originalRange) { selection.removeAllRanges(); selection.addRange(originalRange); } } /**限制名字 */ export function limitName(str) { str = str.slice(0, 3) + "..." + str.slice(str.length - 2, str.length); return str; } } if (!window["vv"]) { window["vv"] = vv } else { for (let i in vv) { window["vv"][i] = vv[i] } } setTimeout(() => { for (let i in window["vv"]) vv[i] = window["vv"][i] }, 0)