# 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 的解决方案，支持多种场景和自动回退机制。
