概述
本文介绍App Inventor 2中常见的图片处理需求:
- 图片缩放(等比/固定尺寸)
- 图片存储到本地/相册
- 图片格式转换
- Canvas绘制图片
- 图片选择和裁剪
图片选择
使用ImagePicker
ImagePicker让用户从手机相册选择图片:
when Button1.Click() {
ImagePicker1.Open()
}
when ImagePicker1.AfterPicking(path) {
if path != "" {
Image1.Picture = path
Label1.Text = join("图片路径:", path)
}
}
使用FilePicker(选择任意文件)
when Button2.Click() {
FilePicker1.Open()
}
when FilePicker1.AfterPicking(path) {
if endsWith(path, ".jpg") || endsWith(path, ".png") {
Image1.Picture = path
}
}
使用Camera拍照
when Button3.Click() {
Camera1.TakePicture()
}
when Camera1.AfterPicture(image) {
Image1.Picture = image
}
图片缩放
方案一:Canvas缩放(推荐)
通过Canvas将图片绘制到指定尺寸:
global sourcePath = ""
global targetWidth = 200
global targetHeight = 200
when Button4.Click() {
Canvas1.Width = global_targetWidth
Canvas1.Height = global_targetHeight
Canvas1.Clear()
Canvas1.DrawImage(global_sourcePath, 0, 0, global_targetWidth, global_targetHeight)
}
when Button5.Click() {
global scaledImage = Canvas1.Save()
Label1.Text = join("已保存:", global_scaledImage)
}
方案二:等比缩放
保持宽高比的缩放:
function scaleSize(origW, origH, maxSide) {
var scaleRatio = 0
var newW = 0
var newH = 0
if origW >= origH {
scaleRatio = maxSide / origW
newW = maxSide
newH = floor(origH * scaleRatio)
} else {
scaleRatio = maxSide / origH
newH = maxSide
newW = floor(origW * scaleRatio)
}
return createDictionary(createPair("width", newW), createPair("height", newH))
}
方案三:WebView + Canvas缩放(精确控制)
使用HTML5 Canvas进行高质量缩放:
<!-- resize.html -->
<canvas id="canvas"></canvas>
<script>
function resizeImage(dataUrl, maxW, maxH) {
var img = new Image();
img.onload = function() {
var ratio = Math.min(maxW / img.width, maxH / img.height);
var w = Math.floor(img.width * ratio);
var h = Math.floor(img.height * ratio);
var canvas = document.getElementById('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, w, h);
window.AppInventor.setWebViewString(canvas.toDataURL('image/jpeg', 0.8));
};
img.src = dataUrl;
}
</script>
图片存储
保存到应用私有目录
when Button6.Click() {
// Canvas保存到应用目录
var savePath = "/sdcard/AppInventor/Assets/my_image.png"
Canvas1.Save()
Label1.Text = join("已保存到:", savePath)
}
保存到相册
使用FileTools扩展或File组件:
// 方案1:使用File组件复制到相册目录
when Button7.Click() {
var srcPath = Canvas1.Save()
var destPath = join("/sdcard/DCIM/Camera/my_photo_", Clock1.FormatDateTime(Clock1.Now(), "yyyyMMdd_HHmmss"), ".png")
File1.SaveFile(File1.ReadFrom(srcPath), destPath)
}
when File1.AfterFileSaved(fileName) {
Label1.Text = join("✅ 已保存到相册:", fileName)
}
注意:Android 10+的分区存储限制,直接写入DCIM目录可能需要特殊权限。推荐使用FileTools扩展的
SaveFileToGallery方法。
使用FileTools扩展
FileTools扩展 提供了直接保存图片到相册的方法:
when Button8.Click() {
FileTools1.SaveFile(global_imagePath, "MyAppPhotos")
}
图片裁剪
Canvas裁剪
global cropX = 50
global cropY = 50
global cropW = 200
global cropH = 200
when Button9.Click() {
// 在Canvas上绘制裁剪区域
Canvas2.Width = global_cropW
Canvas2.Height = global_cropH
Canvas2.Clear()
// drawImage的源区域参数
Canvas2.DrawImage(Image1.Picture, global_cropX, global_cropY, global_cropW, global_cropH, 0, 0, global_cropW, global_cropH)
}
WebView裁剪(支持手势框选)
更灵活的方式是在WebView中用JavaScript实现图片裁剪,支持拖拽选择区域。
图片格式转换
Canvas转Base64
when Button10.Click() {
var base64Data = Canvas1.Save()
Label1.Text = base64Data
}
Base64转图片
when Button11.Click() {
Image1.Picture = join("data:image/png;base64,", TextBox1.Text)
}
实战案例:头像上传
功能需求
- 从相册选择或拍照获取头像
- 等比缩放到200x200
- 圆形裁剪
- 上传到服务器
积木块代码
global avatarPath = ""
when Button12.Click() {
ImagePicker2.Open()
}
when ImagePicker2.AfterPicking(path) {
if path != "" {
global_avatarPath = path
// 缩放到200x200
Canvas1.Width = 200
Canvas1.Height = 200
Canvas1.Clear()
Canvas1.DrawImage(path, 0, 0, 200, 200)
Image1.Picture = Canvas1.Save()
}
}
when Button13.Click() {
var base64 = Canvas1.Save()
Web1.Url = "https://api.example.com/upload/avatar"
Web1.PostText(join("image=", base64))
}
when Web1.GotText(url, responseCode, responseType, responseContent) {
if responseContent == "success" {
Label1.Text = "✅ 头像上传成功"
} else {
Label1.Text = "❌ 上传失败"
}
}
常见问题
Q1: 图片显示变形怎么办?
使用等比缩放,不要强制拉伸。Image组件设置 ScalePictureToFit = true 可以自动等比缩放。
Q2: 大图片导致OOM(内存溢出)?
App Inventor处理大图片(>5MB)容易崩溃。解决方案:
- 先用Canvas缩小到合理尺寸(如1024x1024)
- 使用WebView方案处理大图
- 避免同时加载多张大图
Q3: 图片保存到相册后手机相册看不到?
需要通知系统扫描新文件。使用FileTools扩展的 scanFile 方法:
FileTools1.ScanFile(global_savePath)
或者重启手机后才会出现。
Q4: 如何获取图片的宽高?
App Inventor内置组件不直接提供图片尺寸信息。可以用WebView获取:
var img = new Image();
img.onload = function() {
window.AppInventor.setWebViewString(img.width + "," + img.height);
};
img.src = imagePath;
总结
| 需求 | 推荐方案 |
|---|---|
| 选择图片 | ImagePicker / Camera |
| 缩放图片 | Canvas绘制 |
| 存储到相册 | FileTools扩展 |
| 裁剪图片 | Canvas / WebView |
| 格式转换 | Canvas + Base64 |
| 上传图片 | Web组件 + Base64 |
扫码添加客服咨询