Files
youle_app_android/docs/Canvas_Base64_方案说明.md
2026-02-16 18:18:11 +08:00

141 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WebView Canvas 转 Base64 方案
## 概述
我为您的 `WebViewScreenshotUtil.java` 添加了完整的 Canvas 转 Base64 编码的功能。这个方案提供了多种方法来获取 WebView 中的 Canvas 内容。
## 新增功能
### 1. 基础功能
- `bitmapToBase64()` - 将 Bitmap 转换为 base64 编码
- `captureWebViewToBase64()` - 截取整个 WebView 并转为 base64
### 2. JavaScript 注入方案(推荐)
- `getCanvasBase64FromWebView()` - 通过 JavaScript 获取指定 Canvas 内容
- `getAllCanvasBase64FromWebView()` - 获取页面中所有 Canvas 内容
- `captureCanvasAdvanced()` - 高级方法,自动回退机制
## 使用方法
### 方法1获取指定 Canvas推荐
```java
// 获取 ID 为 "gameCanvas" 的 Canvas 内容
WebViewScreenshotUtil.getCanvasBase64FromWebView(webView, "gameCanvas",
new WebViewScreenshotUtil.CanvasToBase64Callback() {
@Override
public void onSuccess(String base64Data) {
// 成功获取到 base64 数据
Log.d("Canvas", "Base64 length: " + base64Data.length());
// 在这里处理 base64 数据
}
@Override
public void onError(String error) {
Log.e("Canvas", "获取失败: " + error);
}
});
```
### 方法2获取第一个 Canvas
```java
// 传入 null 或空字符串会获取页面中第一个 Canvas
WebViewScreenshotUtil.getCanvasBase64FromWebView(webView, null, callback);
```
### 方法3获取所有 Canvas
```java
WebViewScreenshotUtil.getAllCanvasBase64FromWebView(webView,
new WebViewScreenshotUtil.CanvasToBase64Callback() {
@Override
public void onSuccess(String jsonResult) {
// jsonResult 是包含所有 Canvas 信息的 JSON 字符串
// 格式:[{"index":0,"id":"canvas1","width":800,"height":600,"dataUrl":"data:image/png;base64,..."}]
}
@Override
public void onError(String error) {
// 处理错误
}
});
```
### 方法4高级方法自动回退
```java
// 这个方法会先尝试 JavaScript 方法,失败时自动使用传统截图方法
WebViewScreenshotUtil.captureCanvasAdvanced(webView, "gameCanvas", callback);
```
### 方法5传统 WebView 截图转 base64
```java
// 同步方法,直接返回 base64 字符串
String base64 = WebViewScreenshotUtil.captureWebViewToBase64(webView);
// 或者指定压缩质量0-100
String base64 = WebViewScreenshotUtil.captureWebViewToBase64(webView, 80);
```
## 技术原理
### JavaScript 方案
通过向 WebView 注入 JavaScript 代码,直接调用 HTML5 Canvas 的 `toDataURL()` 方法:
```javascript
// 获取指定 Canvas
var canvas = document.getElementById('canvasId');
var dataUrl = canvas.toDataURL('image/png');
// 获取第一个 Canvas
var canvases = document.getElementsByTagName('canvas');
var dataUrl = canvases[0].toDataURL('image/png');
```
### 传统截图方案
如果 JavaScript 方案失败,会自动回退到传统的 Android View 截图方法。
## 最佳实践
1. **等待加载完成**:确保在 WebView 和 Canvas 完全加载后再进行截图
```java
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// 稍微延迟确保 Canvas 渲染完成
view.postDelayed(() -> {
WebViewScreenshotUtil.captureCanvasAdvanced(webView, "gameCanvas", callback);
}, 1000);
}
});
```
2. **使用高级方法**:推荐使用 `captureCanvasAdvanced()` 方法,它提供了最好的兼容性
3. **错误处理**:始终实现 `onError` 回调来处理可能的失败情况
4. **内存管理**:如果转换为 Bitmap记得及时调用 `bitmap.recycle()` 释放内存
## 兼容性
- **JavaScript 方案**:需要 Android 4.4+ (API 19+)
- **传统截图方案**:支持所有 Android 版本
- 自动回退机制确保在所有设备上都能工作
## 常见问题
1. **Canvas 为空**:确保 Canvas 已经绘制了内容
2. **跨域问题**:如果 Canvas 使用了跨域图片,可能无法导出
3. **硬件加速**:某些情况下可能需要禁用硬件加速
4. **WebGL Canvas**:对于 WebGL Canvas可能需要特殊处理
## 性能优化
1. 对于高频截图,考虑使用较低的压缩质量
2. 大尺寸 Canvas 可以考虑先缩放再转换
3. 异步处理,避免阻塞 UI 线程
这个方案为您提供了完整的 WebView Canvas 转 Base64 的解决方案,支持多种场景和自动回退机制。