cocosCreator导出web工程上传本地图片

2024-09-27 09:30:55 浏览数 (4)

在 Cocos Creator 导出的 Web 项目中实现手机或者电脑上传相册图片,可以使用 HTMLJavaScript 来实现文件选择功能,并将其与 Cocos Creator 项目进行集成。以下是大致的步骤:

(adsbygoogle = window.adsbygoogle || []).push({});

1、在ts脚本中动态创建HTML元素(input文件选择器)

在ts脚本中动态创建HTML元素(input文件选择器,并添加事件)

代码语言:javascript复制
private inputElement;

private creatorInput() {
     this.inputElement = document.createElement('input');
     this.inputElement.type = 'file';
     this.inputElement.accept = 'image/*'; // 仅接受图片文件
     this.inputElement.style.display = 'none'; // 隐藏 input
     document.body.appendChild(this.inputElement);
     this.inputElement.addEventListener('change', (event: Event) => {
          const target = event.target as HTMLInputElement;
          if (target.files && target.files.length > 0) {
          const file = target.files[0];
          this.handleFileUpload(file);
         }
     });
    }
private handleFileUpload(file: File) {
     const reader = new FileReader();
     // 读取文件为 DataURL
     reader.onload = (e) => {
          const imageUrl = e.target?.result as string;
          this.loadTextureInCocos(imgNode,imageUrl); // imgNode为图片显示的节点,即上传的图片会在这个节点渲染
     };
     reader.readAsDataURL(file);
}

private loadTextureInCocos(node: Node, imageUrl: string){
     let image = new Image();
     image.onload = () => {
          let img = new ImageAsset(image)
          let texture = new Texture2D();
          texture.image = img; // 设置纹理的图片
          let spriteFrame = new SpriteFrame();
          spriteFrame.texture = texture;
          node.getComponent(Sprite).spriteFrame = spriteFrame; // 直接设置精灵帧
          node.getComponent(UITransform).setContentSize(width, hight); // 可选,自己设置图片尺寸
     };
     image.src = imageUrl;
}

2、创建上传图片按钮

代码语言:javascript复制
private clickBtn(){
     this.inputElement.click();
}

完成上面2步就可以实现图片上传功能了。

3、优化

上面方法是可行的,但是我这里使用的时候有几点优化 1、上传图片过大时,容易卡住 2、上传图片为长方形时,会显示不全 3、我这里要将长方形的图片只显示一个正方形,即截取中间一部分 优化方案: 1、上传图片的时候对图片大小进行限制 2、将上传的图片进行压缩 3、渲染图片时对图片进行尺寸修改(缩放和裁剪)

示例代码

我这里是将上传的图片首先按照长宽比进行一个正方形的裁剪,以短的那边作为边长。 然后对裁剪后的图片按照我给出的寸尺进行缩放,缩放到我想要的尺寸,再进行压缩,压缩后输出一个jpeg的base64的数据。

代码语言:javascript复制
private inputElement;
private imageUrl;
private creatorInput() {
     this.inputElement = document.createElement('input');
     this.inputElement.type = 'file';
     this.inputElement.accept = 'image/*'; // 仅接受图片文件
     this.inputElement.style.display = 'none'; // 隐藏 input
     document.body.appendChild(this.inputElement);
     this.inputElement.addEventListener('change', (event: Event) => {
          const target = event.target as HTMLInputElement;
          if (target.files && target.files.length > 0) {
          const file = target.files[0];
          this.handleFileUpload(file);
         }
     });
    }
private handleFileUpload(file: File) {
        if (file.size > 1024 * 1024) {  // 限制文件大小为 2MB
            console.error('文件过大,无法上传');
            return;
        }
        const reader = new FileReader();
        // 读取文件为 DataURL
        reader.onload = (e) => {
            const imageUrl = e.target?.result as string;
            Tool.compressImage(imageUrl, 126, 126).then((compressedImageUrl) => {
                this.imageUrl = compressedImageUrl;
                Tool.loadTextureInCocos(this.imgNode, compressedImageUrl, 126, 126);
            });
        };
        reader.readAsDataURL(file);
}

private loadTextureInCocos(node: Node, imageUrl: string){
     let image = new Image();
     image.onload = () => {
          let img = new ImageAsset(image)
          let texture = new Texture2D();
          texture.image = img; // 设置纹理的图片
          let spriteFrame = new SpriteFrame();
          spriteFrame.texture = texture;
          node.getComponent(Sprite).spriteFrame = spriteFrame; // 直接设置精灵帧
          node.getComponent(UITransform).setContentSize(width, hight); // 可选,自己设置图片尺寸
     };
     image.src = imageUrl;
}

public compressImage(url: string, targetWidth: number, targetHeight: number): Promise<string> {
     return new Promise((resolve) => {
          const img = new Image();
          img.src = url;

          img.onload = () => {
               const width = img.width;
               const height = img.height;

               // 计算正方形的边长
               const size = Math.min(width, height);

               // 计算截取的正方形区域
               const startX = (width - size) / 2; // 中心点
               const startY = (height - size) / 2; // 中心点

               // 创建画布来截取正方形
               const canvas = document.createElement('canvas');
               canvas.width = size;
               canvas.height = size;

               const ctx = canvas.getContext('2d');
               ctx?.drawImage(img, startX, startY, size, size, 0, 0, size, size); // 截取并绘制正方形

               // 创建一个新的画布以进行缩放
               const scaledCanvas = document.createElement('canvas');
               scaledCanvas.width = targetWidth;
               scaledCanvas.height = targetHeight;
               const scaledCtx = scaledCanvas.getContext('2d');

               // 按比例缩放图像
               scaledCtx?.drawImage(canvas, 0, 0, size, size, 0, 0, targetWidth, targetHeight);

               // 输出压缩后的图片
               resolve(scaledCanvas.toDataURL('image/jpeg', 0.5)); // 使用 JPEG 格式压缩
          };
     });
}
public loadTextureInCocos(node: Node, imageUrl: string, width, hight) {
     let image = new Image();
     image.onload = () => {
          let img = new ImageAsset(image)
          let texture = new Texture2D();
          texture.image = img; // 设置纹理的图片
          let spriteFrame = new SpriteFrame();
          spriteFrame.texture = texture;
          node.getComponent(Sprite).spriteFrame = spriteFrame; // 直接设置精灵帧
          node.getComponent(UITransform).setContentSize(width, hight);
     };
     image.src = imageUrl;
}

private clickBtn(){
     this.inputElement.click();
}

5、代码解读

文件选择事件:我们为文件选择器设置了 change 事件监听器,当用户选择图片时,会调用 handleFileUpload() 方法。

FileReader 读取图片``:FileReader 用来读取用户上传的图片,并将其转换为 Base64 数据 URL 格式。

6、注意事项

跨域问题:确保你的服务器支持 https,否则某些浏览器可能会限制上传功能的使用。 UI布局:上传按钮的位置可以根据你的游戏场景动态调整。 性能考虑:如果图片过大,可能会导致内存消耗过多,可以在上传前对图片进行压缩。

1 人点赞