在 Cocos Creator 导出的 Web 项目中实现手机或者电脑上传相册图片,可以使用 HTML
和 JavaScript
来实现文件选择功能,并将其与 Cocos Creator 项目进行集成。以下是大致的步骤:
(adsbygoogle = window.adsbygoogle || []).push({});
1、在ts脚本中动态创建HTML元素(input
文件选择器)
在ts脚本中动态创建HTML元素(input
文件选择器,并添加事件)
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布局
:上传按钮的位置可以根据你的游戏场景动态调整。
性能考虑
:如果图片过大,可能会导致内存消耗过多,可以在上传前对图片进行压缩。