cocos creater 游戏开发工具方法

/**
 * 观察者方法
 *
 * @export
 * @param {*} obj
 * @param {Function} callback
 * @param {*} pointer
 * @return {*}  {ProxyConstructor}
 */
export function observer(
  obj: any,
  callback: Function,
  pointer: any
): ProxyConstructor {
  return new Proxy<ProxyConstructor>(obj, {
    set(target, property, value, reciever): boolean {
      if (target[property] !== value) callback.call(pointer, value);
      Reflect.set(target, property, value, reciever);
      return true;
    },
  });
}
/**
 * 加载远程url资源方法
 *
 * @export
 * @param {string} path
 * @return {*}  {Promise}
 */
export function loadRemote(path: string): Promise<any> {
  return new Promise<any>((resolve, reject) => {
    cc.assetManager.loadRemote(path, (error, asset) => {
      if (error) reject(error);
      resolve(asset);
    });
  });
}
/**
 * 加载本地resources资源方法
 *
 * @export
 * @param {string} path
 * @return {*}  {Promise}
 */
export function loadRes(path: string): Promise<any> {
  return new Promise<any>((resolve, reject) => {
    cc.resources.load(path, (error, asset) => {
      if (error) reject(error);
      resolve(asset);
    });
  });
}
/**
 * 延时执行方法
 *
 * @export
 * @param {number} time
 * @return {*}  {Promise}
 */
export function delay(time: number): Promise<boolean> {
  return new Promise<boolean>((resolve, reject) => {
    setTimeout(() => {
      resolve(true);
    }, time);
  });
}
/**
 * 生成随机数方法
 * @param Min 最小数
 * @param Max 最大数
 * @returns min ≤ r ≤ max
 */
export function randomNumBoth(Min: number, Max: number): number {
  let Range: number = Max - Min;
  let Rand: number = Math.random();
  let num: number = Min + Math.round(Rand * Range); //四舍五入
  return num;
}
/**
 * 多选一方法
 * @param arr 数组
 * @returns 数组中任意的一个元素
 */
export function manyToOne(arr: Array<any>): any {
  let key = Math.floor(Math.random() * arr.length);
  let val = arr[key];
  // return [key, val];
  return val;
}
/**
 * 深拷贝
 *
 * @param {*} obj
 * @return {*}
 */
export function deepClone(obj: any): any {
  // 判断是否是对象,不是对象,返回结果(返回值类型)
  // obj == null判断了null和undefined两种情况  null==undefined
  if (typeof obj !== "object" || obj == null) {
    return obj;
  }
  // 初始化结果数据,如果是数组赋值为[],否则为{}
  let result = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    // 判断是否是自己的属性方法,而不是原型属性方法
    // 如果是递归复制
    if (obj.hasOwnProperty(key)) {
      result[key] = deepClone(obj[key]);
    }
  }
  return result;
}
/**
 * 一天剩余时间(毫秒)
 * @returns 剩余时间
 */
export const timeRemainingToday = (): number => {
  const today = new Date();
  const tomorrowNow = new Date(today);
  tomorrowNow.setDate(today.getDate() + 1);
  const tomorrow = new Date(
    tomorrowNow.getFullYear(),
    tomorrowNow.getMonth(),
    tomorrowNow.getDate()
  );
  return tomorrow.getTime() - today.getTime();
};
/**
 * 编码方法
 */
export const encode = (data) =>
  window.btoa(encodeURIComponent(JSON.stringify(data)));
/**
 * 解码方法
 */
export const decode = (data) =>
  JSON.parse(decodeURIComponent(window.atob(data)));
/**
 * 获取网址的值
 * @param 网址
 * @returns 值
 */
export function getQueryVariable(variable: string): string {
  const query = window.location.search.substring(1);
  const vars = query.split("&");
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split("=");
    if (pair[0] == variable) {
      return pair[1];
    }
  }
  return "";
}
/**
 * storage
 */
export const storage = {
  //存储
  set(key, value) {
    localStorage.setItem(key, encode(value));
  },
  //取出数据
  get(key) {
    let data = localStorage.getItem(key);
    if (data != null && data != "") {
      data = decode(data);
      return data;
    } else {
      return null;
    }
  },
  // 删除数据
  remove(key) {
    localStorage.removeItem(key);
  },
};
/**
 * 判断是否是手机的方法
 * @returns 是否手机
 */
export function isMobile() {
  return !!navigator.userAgent.match(
    /(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i
  );
}
/**
 * 通过img获取base64格式图片
 * @param img
 * @returns
 */
export function getBase64Image(img) {
  let canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  let ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0, img.width, img.height);
  let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
  let dataURL = canvas.toDataURL("image/" + ext);
  return dataURL;
}
/**
 * 通过src获取base64格式图片
 * @param src
 * @returns
 */
export function getBase64ImageByUrl(src) {
  return new Promise<string>((resolve, reject) => {
    let image = new Image();
    image.crossOrigin = "";
    image.src = src;
    image.onload = function () {
      let base64 = getBase64Image(image);
      resolve(base64);
    };
  });
}
/**
 * 下载图片方法
 * @param imgsrc 图片路径
 * @param name 图片名称
 */
export function downloadIamge(imgsrc, name) {
  //下载图片地址和图片名
  let image = new Image();
  // 解决跨域 Canvas 污染问题
  image.setAttribute("crossOrigin", "anonymous");
  image.onload = function () {
    let canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    let context = canvas.getContext("2d");
    context.drawImage(image, 0, 0, image.width, image.height);
    let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
    let a = document.createElement("a"); // 生成一个a元素
    let event = new MouseEvent("click"); // 创建一个单击事件
    a.download = name || "photo"; // 设置图片名称
    a.href = url; // 将生成的URL设置为a.href属性
    a.dispatchEvent(event); // 触发a的单击事件
  };
  image.src = imgsrc;
}
/**
 * cocos截图方法
 * @param node 节点
 */
export function screenshot(node: cc.Node) {
  return new Promise<string>((resolve, reject) => {
    let nodeCamera = new cc.Node();
    nodeCamera.parent = cc.find("Canvas");
    let camera = nodeCamera.addComponent(cc.Camera);

    let position = node.getPosition();
    let width = node.width * node.scaleX;
    let height = node.height * node.scaleY;

    // 当 alignWithScreen 为 true 的时候,摄像机会自动将视窗大小调整为整个屏幕的大小。如果想要完全自由地控制摄像机,则需要将 alignWithScreen 设置为 false。(v2.2.1 新增)
    camera.alignWithScreen = false;
    // 设置摄像机的投影模式是正交(true)还是透视(false)模式
    camera.ortho = true;
    // 摄像机在正交投影模式下的视窗大小。该属性在 alignWithScreen 设置为 false 时生效。
    camera.orthoSize = height / 2;

    let texture = new cc.RenderTexture();
    // 如果截图内容中不包含 Mask 组件,可以不用传递第三个参数
    texture.initWithSize(
      width,
      height,
      cc.game["_renderContext"].STENCIL_INDEX8
    );

    // 如果设置了 targetTexture,那么摄像机渲染的内容不会输出到屏幕上,而是会渲染到 targetTexture 上。
    camera.targetTexture = texture;

    node.setPosition(cc.Vec2.ZERO);
    // 渲染一次摄像机,即更新一次内容到 RenderTexture 中
    camera.render(node);
    node.setPosition(position);

    // 从 render texture 读取像素数据,数据类型为 RGBA 格式的 Uint8Array 数组。
    // 默认每次调用此函数会生成一个大小为 (长 x 高 x 4) 的 Uint8Array。
    let data = texture.readPixels();

    // 创建画布
    let canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    let ctx = canvas.getContext("2d");
    // write the render data
    // 1 像素 = 32 bit(RGBA),1 byte = 8 bit,所以 1 像素 = 4 byte
    // 每行 width 像素,即 width * 4 字节
    let rowBytes = width * 4;
    for (let row = 0; row < height; row++) {
      // RenderTexture 得到的纹理是上下翻转的
      let srow = height - 1 - row;
      let imageData = ctx.createImageData(width, 1);
      let start = srow * width * 4;
      for (let i = 0; i < rowBytes; i++) {
        imageData.data[i] = data[start + i];
      }

      ctx.putImageData(imageData, 0, row);
    }

    let dataURL = canvas.toDataURL("image/jpeg");
    nodeCamera.destroy();

    resolve(dataURL);
  });
}
/**
 * cocos截图返回精灵方法
 * @param node 节点
 */
export function screenshotSpriteFrame(node: cc.Node) {
  return new Promise<cc.SpriteFrame>(async (resolve, reject) => {
    const dataURL = await screenshot(node);
    let img = document.createElement("img");
    img.src = dataURL;
    let texture2D = new cc.Texture2D();
    texture2D.initWithElement(img);
    let spriteFrame = new cc.SpriteFrame();
    spriteFrame.setTexture(texture2D);
    resolve(spriteFrame);
  });
}
/**
 * cocos渲染节点截图方法
 * @param node 节点
 */
export function renderNode(nodeCapture: cc.Node) {
  return new Promise<string>((resolve, reject) => {
    let nodeCamera = new cc.Node();
    nodeCamera.parent = cc.find("Canvas");
    let camera = nodeCamera.addComponent(cc.Camera);

    let position = nodeCapture.getPosition();
    let width = nodeCapture.width * nodeCapture.scaleX;
    let height = nodeCapture.height * nodeCapture.scaleY;

    // 当 alignWithScreen 为 true 的时候,摄像机会自动将视窗大小调整为整个屏幕的大小。如果想要完全自由地控制摄像机,则需要将 alignWithScreen 设置为 false。(v2.2.1 新增)
    camera.alignWithScreen = false;
    // 设置摄像机的投影模式是正交(true)还是透视(false)模式
    camera.ortho = true;
    // 摄像机在正交投影模式下的视窗大小。该属性在 alignWithScreen 设置为 false 时生效。
    camera.orthoSize = height / 2;

    let texture = new cc.RenderTexture();
    // 如果截图内容中不包含 Mask 组件,可以不用传递第三个参数
    texture.initWithSize(
      width,
      height,
      cc.RenderTexture.DepthStencilFormat.RB_FMT_S8
    );

    // 如果设置了 targetTexture,那么摄像机渲染的内容不会输出到屏幕上,而是会渲染到 targetTexture 上。
    camera.targetTexture = texture;

    // 创建画布
    let canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;

    let ctx = canvas.getContext("2d");

    nodeCapture.setPosition(cc.Vec2.ZERO);
    // 渲染一次摄像机,即更新一次内容到 RenderTexture 中
    camera.render(nodeCapture);
    nodeCapture.setPosition(position);

    // 从 render texture 读取像素数据,数据类型为 RGBA 格式的 Uint8Array 数组。
    // 默认每次调用此函数会生成一个大小为 (长 x 高 x 4) 的 Uint8Array。
    let data = texture.readPixels();
    // write the render data
    // PNG 中 1 像素 = 32 bit(RGBA),1 byte = 8 bit,所以 1 像素 = 4 byte
    // 每行 width 像素,即 width * 4 字节
    let rowBytes = width * 4;
    for (let row = 0; row < height; row++) {
      // RenderTexture 得到的纹理是上下翻转的
      let srow = height - 1 - row;
      let imageData = ctx.createImageData(width, 1);
      let start = srow * width * 4;
      for (let i = 0; i < rowBytes; i++) {
        imageData.data[i] = data[start + i];
      }

      ctx.putImageData(imageData, 0, row);
    }

    let dataURL = canvas.toDataURL("image/png");
    let img = document.createElement("img");
    img.src = dataURL;

    nodeCamera.destroy();

    let texture2D = new cc.Texture2D();
    texture2D.initWithElement(img);

    let spriteFrame = new cc.SpriteFrame();
    spriteFrame.setTexture(texture2D);

    let node = new cc.Node();
    let sprite = node.addComponent(cc.Sprite);
    sprite.spriteFrame = spriteFrame;

    resolve(dataURL);
  });
}
/**
 * cocos creater 截屏方法
 * 分享数据页
 * orthoSize 视窗大小,用于调整截图避免出现黑边或者白边
 * @returns 图片
 */
export function screenNode(
  nd: cc.Node,
  orthoSize: number = 750,
  w: number = 750,
  h: number = 1464
) {
  let node = nd;
  let camera = node?.getComponent(cc.Camera);
  if (!camera) {
    camera = node.addComponent(cc.Camera);
  }

  // 设置你想要的截图内容的 cullingMask
  // camera.cullingMask = 0xffffffff;

  // 新建一个 RenderTexture,并且设置 camera 的 targetTexture 为新建的 RenderTexture,这样 camera 的内容将会渲染到新建的 RenderTexture 中。
  let texture = new cc.RenderTexture();

  //区域截图关闭这个
  camera.alignWithScreen = false;

  // let gl = cc.game._renderContext; //gl.STENCIL_INDEX8
  //尺寸固定750*1624
  texture.initWithSize(w, h, cc.RenderTexture.DepthStencilFormat.RB_FMT_S8); //(node.width,node.height,cc.RenderTexture.DepthStencilFormat.RB_FMT_S8);  //(cc.visibleRect.width, cc.visibleRect.height);
  camera.targetTexture = texture;

  //设置合适的比例,避免出现黑边或者白边
  camera.orthoSize = orthoSize * node.anchorX * 0.975; //node.width* node.scaleX * 1.07;//截头像的比例 0.5 //截数据页的比例1.07

  // camera.backgroundColor = cc.Color.TRANSPARENT;

  // 渲染一次摄像机,即更新一次内容到 RenderTexture 中
  camera.render();

  // 这样我们就能从 RenderTexture 中获取到数据了
  let data = texture.readPixels();

  // 接下来就可以对这些数据进行操作了
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  canvas.width = texture.width;
  canvas.height = texture.height;

  let width = texture.width;
  let height = texture.height;

  let rowBytes = width * 4;
  for (let row = 0; row < height; row++) {
    let srow = height - 1 - row;
    let imageData = ctx.createImageData(width, 1);
    let start = srow * width * 4;
    for (let i = 0; i < rowBytes; i++) {
      imageData.data[i] = data[start + i];
    }

    ctx.putImageData(imageData, 0, row);
  }

  let dataURL = canvas.toDataURL("image/jpeg");
  // let img = document.createElement("img");
  // img.src = dataURL;
  return dataURL;
}
/**
 * cocos截取图片方法
 * @param node 节点
 */
export function captureNode(nodeCapture: cc.Node) {
  return new Promise<cc.SpriteFrame>((resolve, reject) => {
    let nodeCamera = new cc.Node();
    nodeCamera.parent = cc.find("Canvas");
    let camera = nodeCamera.addComponent(cc.Camera);

    let width = nodeCapture.width;
    let height = nodeCapture.height;

    let texture = new cc.RenderTexture();
    texture.initWithSize(
      cc.visibleRect.width,
      cc.visibleRect.height,
      cc.RenderTexture.DepthStencilFormat.RB_FMT_S8
    );

    camera.targetTexture = texture;

    let canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;

    let ctx = canvas.getContext("2d");
    camera.render();

    // 指定需要读取的区域的像素
    let size = nodeCapture.getContentSize();
    let pixels = new Uint8Array(size.width * size.height * 4);
    let x = texture.width / 2 - nodeCapture.width / 2;
    let y = texture.height / 2 - nodeCapture.height / 2;
    let w = nodeCapture.width;
    let h = nodeCapture.height;
    let data = texture.readPixels(pixels, x, y, w, h);

    // write the render data
    let rowBytes = width * 4;
    for (let row = 0; row < height; row++) {
      let srow = height - 1 - row;
      let imageData = ctx.createImageData(width, 1);
      let start = srow * width * 4;
      for (let i = 0; i < rowBytes; i++) {
        imageData.data[i] = data[start + i];
      }

      ctx.putImageData(imageData, 0, row);
    }

    let dataURL = canvas.toDataURL("image/png");
    let img = document.createElement("img");
    img.src = dataURL;

    let texture2D = new cc.Texture2D();
    texture2D.initWithElement(img);

    let spriteFrame = new cc.SpriteFrame();
    spriteFrame.setTexture(texture2D);

    let node = new cc.Node();
    let sprite = node.addComponent(cc.Sprite);
    sprite.spriteFrame = spriteFrame;

    // return node;
    resolve(spriteFrame);
  });
}
  
/**
 * 截圆形头像图
 * @param avatar 头像
 * @param frame 头像框
 */
export function captureAvatar(avatar,frame) {
    return new Promise<string>((resolve, reject) => {
          let canvas = document.createElement("canvas");
          //?头像尺寸待定
          let w = 600;
          let h = 600;
          canvas.width = w;
          canvas.height = h;

          let ctx = canvas.getContext("2d");
          ctx.rect(0, 0, canvas.width, canvas.height);
          ctx.fillStyle = "rgba(255, 255, 255, 0)";
          ctx.fill();

          // return;

          let img = document.createElement("img");
          img.src = frame;

          let bgImage = document.createElement("img");
          bgImage.src = avatar;
          bgImage.crossOrigin = "Anonymous";
          bgImage.onload = function () {
            let circle = {
              x: w / 2,
              y: h / 2,
              r: w / 2,
            };
            ctx.clearRect(0, 0, w, h);
            ctx.save();
            ctx.beginPath();
            ctx.arc(circle.x, circle.y, circle.r, 0, Math.PI * 2, false);
            ctx.clip();

            ctx.drawImage(bgImage, 0, 0, 600, 600);
            ctx.drawImage(img, 0, 0, 600, 600);

            let base64 = canvas.toDataURL("image/png");
            // let img2 = document.createElement("img");
            // img2.src = base64;
            resolve(base64);
          };
    });
  }
  
/**
 * 清除对象中的空属性
 * @param obj 对象
 * @returns 对象
 */
export function clearEmpty(obj: any) {
  const clearFun = () => {
    for (const key in obj) {
      if (
        ["[object Object]"].includes(
          Object.prototype.toString.call(obj[key])
        ) &&
        Object.keys(obj[key]).length > 0
      ) {
        clearEmpty(obj[key]);
      } else {
        if (
          ["", null, undefined].includes(obj[key]) ||
          (["[object Object]"].includes(
            Object.prototype.toString.call(obj[key])
          ) &&
            Object.keys(obj[key]).length === 0)
        ) {
          delete obj[key];
        }
      }
    }
    return obj;
  };
  // 第一次清理空属性
  clearFun();
  // 第二次清理空对象
  return clearFun();
}

/**
 * 判断是否是当天函数
 * @param timeStamp 时间戳
 * @returns 
 */
export function isToday(timeStamp){
    if(!timeStamp) return false;
    return !!(new Date(Number(timeStamp)).toDateString() === new Date().toDateString());
}
/**
 * 返回当前场景中的canvas节点
 * @returns 
 */
export function getCanvas() {
        return <any>director.getScene().getChildByName("Canvas");
}
/**
 * base64解密
 */
export function decode(input) {
      // private method for UTF-8 decoding  
    const _utf8_decode = function (utftext) {
        let string = "";
        let i = 0;
        let c = 0;
        let c1 = 0;
        let c2 = 0;
        while (i < utftext.length) {    
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c1 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
                i += 2;
            } else {
                c1 = utftext.charCodeAt(i + 1);
                c2 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
                i += 3;
            }
        }
        return string;
    }
    let _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    let output = "";
    let chr1, chr2, chr3;
    let enc1, enc2, enc3, enc4;
    let i = 0;
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    while (i < input.length) {
        enc1 = _keyStr.indexOf(input.charAt(i++));
        enc2 = _keyStr.indexOf(input.charAt(i++));
        enc3 = _keyStr.indexOf(input.charAt(i++));
        enc4 = _keyStr.indexOf(input.charAt(i++));
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output = output + String.fromCharCode(chr1);
        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }
    }
    output = _utf8_decode(output);
    return output;
}
/**
 * 是否是对象函数
 * @param {对象} obj
 */
export function isObj(obj) {
    // @ts-ignore
    return ["[object Object]"].includes(Object.prototype.toString.call(obj));
  }
/**
 * 更新属性函数(深度搜索算法)
 * @param {目标属性} targetParams
 * @param {更新属性} params
 */
export function updateProps(targetParams, params) {
    if (!targetParams ?? !isObj(targetParams)) targetParams = {};
    if (!isObj(params)) return params;
    Object.keys(params).forEach((key) => {
      if (isObj(params[key])) {
        targetParams[key] = targetParams?.[key] ?? {};
        updateProps(targetParams[key], params[key]);
      } else {
        if (targetParams[key] !== params[key]) {
          targetParams[key] = params[key];
        }
      }
    });
    return targetParams;
  }

你可能感兴趣的:(web,typescript,javascript,前端,cocos)