OpenClaw Canvas:可视化界面入门

目录

    • 摘要
    • [1. 引言 - 为什么需要 Canvas?](#1. 引言 - 为什么需要 Canvas?)
      • [1.1 Canvas 的价值](#1.1 Canvas 的价值)
      • [1.2 Canvas 架构](#1.2 Canvas 架构)
      • [1.3 Canvas 能力概览](#1.3 Canvas 能力概览)
    • [2. Canvas 基础操作](#2. Canvas 基础操作)
      • [2.1 展示界面 (present)](#2.1 展示界面 (present))
      • [2.2 导航页面 (navigate)](#2.2 导航页面 (navigate))
      • [2.3 执行脚本 (eval)](#2.3 执行脚本 (eval))
      • [2.4 截图 (snapshot)](#2.4 截图 (snapshot))
    • [3. 展示 HTML 内容](#3. 展示 HTML 内容)
      • [3.1 基本用法](#3.1 基本用法)
      • [3.2 带样式的界面](#3.2 带样式的界面)
      • [3.3 响应式设计](#3.3 响应式设计)
    • [4. 展示外部网页](#4. 展示外部网页)
      • [4.1 基本用法](#4.1 基本用法)
      • [4.2 设置尺寸](#4.2 设置尺寸)
      • [4.3 嵌入文档](#4.3 嵌入文档)
    • [5. 实战案例一:数据仪表盘](#5. 实战案例一:数据仪表盘)
      • [5.1 场景描述](#5.1 场景描述)
      • [5.2 实现代码](#5.2 实现代码)
    • [6. 实战案例二:交互式表单](#6. 实战案例二:交互式表单)
      • [6.1 场景描述](#6.1 场景描述)
      • [6.2 实现代码](#6.2 实现代码)
    • [7. 实战案例三:报告展示](#7. 实战案例三:报告展示)
      • [7.1 场景描述](#7.1 场景描述)
      • [7.2 实现代码](#7.2 实现代码)
    • [8. 高级功能](#8. 高级功能)
      • [8.1 执行 JavaScript](#8.1 执行 JavaScript)
      • [8.2 获取截图](#8.2 获取截图)
      • [8.3 A2UI 交互](#8.3 A2UI 交互)
    • [9. 最佳实践](#9. 最佳实践)
      • [9.1 设计原则](#9.1 设计原则)
      • [9.2 常见问题](#9.2 常见问题)
    • [10. 总结](#10. 总结)
      • [10.1 核心要点](#10.1 核心要点)
      • [10.2 下一步](#10.2 下一步)
    • 参考资料

摘要

本文介绍 OpenClaw 框架中的 Canvas 可视化界面功能。从 Canvas 基本概念、核心操作、界面展示到实际应用,全面解析如何通过 AI Agent 创建和管理可视化界面。通过实际案例演示网页嵌入、自定义界面、交互式应用等场景,帮助开发者构建具有可视化能力的智能应用。🎨


1. 引言 - 为什么需要 Canvas?

1.1 Canvas 的价值

场景 说明 示例
可视化展示 展示图表、报告 数据仪表盘
交互界面 提供用户交互 配置面板
网页嵌入 嵌入外部网页 文档、工具
实时预览 实时展示结果 代码预览

1.2 Canvas 架构

OpenClaw Canvas
AI Agent
Canvas Tool
操作类型
present - 展示界面
navigate - 导航URL
eval - 执行JS
snapshot - 截图
渲染界面
获取截图

1.3 Canvas 能力概览

能力 说明 Action
展示界面 展示 HTML/URL present
导航页面 加载指定 URL navigate
执行脚本 运行 JavaScript eval
截图 捕获界面图像 snapshot
A2UI 交互式界面 a2ui_push

2. Canvas 基础操作

2.1 展示界面 (present)

python 复制代码
canvas(
    action="present",
    url="https://example.com"  # 或使用 html 参数
)

2.2 导航页面 (navigate)

python 复制代码
canvas(
    action="navigate",
    url="https://example.com"
)

2.3 执行脚本 (eval)

python 复制代码
canvas(
    action="eval",
    javaScript="document.title"
)

2.4 截图 (snapshot)

python 复制代码
canvas(
    action="snapshot",
    outputFormat="png"  # 或 "jpg"
)

3. 展示 HTML 内容

3.1 基本用法

python 复制代码
canvas(
    action="present",
    html="""
    <!DOCTYPE html>
    <html>
    <head>
        <title>Hello Canvas</title>
    </head>
    <body>
        <h1>Hello, OpenClaw Canvas!</h1>
        <p>这是一个简单的 HTML 页面</p>
    </body>
    </html>
    """
)

3.2 带样式的界面

python 复制代码
canvas(
    action="present",
    html="""
    <!DOCTYPE html>
    <html>
    <head>
        <style>
            body {
                font-family: Arial, sans-serif;
                padding: 20px;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
            }
            .card {
                background: rgba(255,255,255,0.1);
                padding: 20px;
                border-radius: 10px;
                backdrop-filter: blur(10px);
            }
            h1 { margin: 0; }
        </style>
    </head>
    <body>
        <div class="card">
            <h1>📊 数据仪表盘</h1>
            <p>实时数据展示</p>
        </div>
    </body>
    </html>
    """
)

3.3 响应式设计

python 复制代码
canvas(
    action="present",
    html="""
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            .container {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 20px;
                padding: 20px;
            }
            .item {
                background: #f5f5f5;
                padding: 20px;
                border-radius: 8px;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="item">项目 1</div>
            <div class="item">项目 2</div>
            <div class="item">项目 3</div>
            <div class="item">项目 4</div>
        </div>
    </body>
    </html>
    """
)

4. 展示外部网页

4.1 基本用法

python 复制代码
canvas(
    action="present",
    url="https://docs.openclaw.ai"
)

4.2 设置尺寸

python 复制代码
canvas(
    action="present",
    url="https://example.com",
    width=800,
    height=600
)

4.3 嵌入文档

python 复制代码
def show_documentation():
    """展示 OpenClaw 文档"""
    canvas(
        action="present",
        url="https://docs.openclaw.ai",
        width=1000,
        height=700
    )

5. 实战案例一:数据仪表盘

5.1 场景描述

创建一个实时数据展示仪表盘。

5.2 实现代码

python 复制代码
def show_dashboard(data):
    """展示数据仪表盘"""
    html = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <title>数据仪表盘</title>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
        <style>
            body {{
                font-family: 'Segoe UI', Arial, sans-serif;
                background: #1a1a2e;
                color: white;
                padding: 20px;
                margin: 0;
            }}
            .header {{
                text-align: center;
                margin-bottom: 30px;
            }}
            .stats {{
                display: grid;
                grid-template-columns: repeat(4, 1fr);
                gap: 20px;
                margin-bottom: 30px;
            }}
            .stat-card {{
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                padding: 20px;
                border-radius: 10px;
                text-align: center;
            }}
            .stat-value {{
                font-size: 2em;
                font-weight: bold;
            }}
            .stat-label {{
                opacity: 0.8;
            }}
            .chart-container {{
                background: #16213e;
                padding: 20px;
                border-radius: 10px;
            }}
        </style>
    </head>
    <body>
        <div class="header">
            <h1>📊 实时数据仪表盘</h1>
            <p>数据更新时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
        </div>
        
        <div class="stats">
            <div class="stat-card">
                <div class="stat-value">{data['total_users']}</div>
                <div class="stat-label">总用户数</div>
            </div>
            <div class="stat-card">
                <div class="stat-value">{data['active_users']}</div>
                <div class="stat-label">活跃用户</div>
            </div>
            <div class="stat-card">
                <div class="stat-value">{data['requests']}</div>
                <div class="stat-label">请求数</div>
            </div>
            <div class="stat-card">
                <div class="stat-value">{data['success_rate']}%</div>
                <div class="stat-label">成功率</div>
            </div>
        </div>
        
        <div class="chart-container">
            <canvas id="chart"></canvas>
        </div>
        
        <script>
            const ctx = document.getElementById('chart').getContext('2d');
            new Chart(ctx, {{
                type: 'line',
                data: {{
                    labels: {data['labels']},
                    datasets: [{{
                        label: '请求数',
                        data: {data['values']},
                        borderColor: '#667eea',
                        backgroundColor: 'rgba(102, 126, 234, 0.1)',
                        fill: true
                    }}]
                }},
                options: {{
                    responsive: true,
                    plugins: {{
                        legend: {{
                            labels: {{ color: 'white' }}
                        }}
                    }},
                    scales: {{
                        y: {{
                            ticks: {{ color: 'white' }},
                            grid: {{ color: 'rgba(255,255,255,0.1)' }}
                        }},
                        x: {{
                            ticks: {{ color: 'white' }},
                            grid: {{ color: 'rgba(255,255,255,0.1)' }}
                        }}
                    }}
                }}
            }});
        </script>
    </body>
    </html>
    """
    
    canvas(action="present", html=html)

6. 实战案例二:交互式表单

6.1 场景描述

创建一个可交互的配置表单。

6.2 实现代码

python 复制代码
def show_config_form():
    """展示配置表单"""
    html = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>配置面板</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                background: #f5f5f5;
                padding: 20px;
            }
            .form-container {
                max-width: 500px;
                margin: 0 auto;
                background: white;
                padding: 30px;
                border-radius: 10px;
                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            }
            h2 {
                margin-top: 0;
                color: #333;
            }
            .form-group {
                margin-bottom: 20px;
            }
            label {
                display: block;
                margin-bottom: 5px;
                font-weight: bold;
                color: #555;
            }
            input, select {
                width: 100%;
                padding: 10px;
                border: 1px solid #ddd;
                border-radius: 5px;
                box-sizing: border-box;
            }
            .btn {
                background: #667eea;
                color: white;
                border: none;
                padding: 12px 24px;
                border-radius: 5px;
                cursor: pointer;
                font-size: 16px;
            }
            .btn:hover {
                background: #5a6fd6;
            }
        </style>
    </head>
    <body>
        <div class="form-container">
            <h2>⚙️ 配置面板</h2>
            
            <div class="form-group">
                <label>模型选择</label>
                <select id="model">
                    <option value="gpt-4">GPT-4</option>
                    <option value="gpt-3.5-turbo">GPT-3.5 Turbo</option>
                    <option value="claude-3">Claude 3</option>
                </select>
            </div>
            
            <div class="form-group">
                <label>温度参数</label>
                <input type="number" id="temperature" value="0.7" min="0" max="2" step="0.1">
            </div>
            
            <div class="form-group">
                <label>最大Token数</label>
                <input type="number" id="max_tokens" value="2000" min="100" max="8000">
            </div>
            
            <button class="btn" onclick="submitConfig()">保存配置</button>
        </div>
        
        <script>
            function submitConfig() {
                const config = {
                    model: document.getElementById('model').value,
                    temperature: parseFloat(document.getElementById('temperature').value),
                    max_tokens: parseInt(document.getElementById('max_tokens').value)
                };
                console.log('配置已保存:', config);
                alert('配置已保存!');
            }
        </script>
    </body>
    </html>
    """
    
    canvas(action="present", html=html)

7. 实战案例三:报告展示

7.1 场景描述

展示格式化的报告内容。

7.2 实现代码

python 复制代码
def show_report(title, content, stats):
    """展示报告"""
    html = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <title>{title}</title>
        <style>
            body {{
                font-family: 'Georgia', serif;
                max-width: 800px;
                margin: 0 auto;
                padding: 40px;
                background: #fafafa;
            }}
            .report {{
                background: white;
                padding: 40px;
                border-radius: 10px;
                box-shadow: 0 2px 20px rgba(0,0,0,0.1);
            }}
            h1 {{
                color: #333;
                border-bottom: 3px solid #667eea;
                padding-bottom: 10px;
            }}
            .meta {{
                color: #888;
                font-size: 0.9em;
                margin-bottom: 30px;
            }}
            .content {{
                line-height: 1.8;
                color: #444;
            }}
            .stats-box {{
                background: #f8f9fa;
                padding: 20px;
                border-radius: 8px;
                margin: 20px 0;
            }}
            .stats-box h3 {{
                margin-top: 0;
                color: #667eea;
            }}
            .stat-item {{
                display: flex;
                justify-content: space-between;
                padding: 10px 0;
                border-bottom: 1px solid #eee;
            }}
        </style>
    </head>
    <body>
        <div class="report">
            <h1>{title}</h1>
            <div class="meta">
                生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
            </div>
            
            <div class="content">
                {content}
            </div>
            
            <div class="stats-box">
                <h3>📊 统计数据</h3>
                <div class="stat-item">
                    <span>总字数</span>
                    <span>{stats['words']}</span>
                </div>
                <div class="stat-item">
                    <span>段落数</span>
                    <span>{stats['paragraphs']}</span>
                </div>
                <div class="stat-item">
                    <span>预计阅读时间</span>
                    <span>{stats['read_time']} 分钟</span>
                </div>
            </div>
        </div>
    </body>
    </html>
    """
    
    canvas(action="present", html=html)

8. 高级功能

8.1 执行 JavaScript

python 复制代码
def update_canvas_data(data):
    """更新 Canvas 中的数据"""
    canvas(
        action="eval",
        javaScript=f"""
        document.getElementById('data-display').textContent = '{data}';
        """
    )

8.2 获取截图

python 复制代码
def capture_canvas():
    """截取 Canvas 内容"""
    screenshot = canvas(
        action="snapshot",
        outputFormat="png"
    )
    return screenshot

8.3 A2UI 交互

python 复制代码
def push_interactive_ui():
    """推送交互式界面"""
    canvas(
        action="a2ui_push",
        jsonl="""
        {"type": "text", "content": "Hello"}
        {"type": "button", "label": "Click me", "action": "click"}
        """
    )

9. 最佳实践

9.1 设计原则

原则 说明
简洁清晰 界面简洁,信息清晰
响应式 适配不同尺寸
性能优化 避免过多资源
用户体验 良好的交互反馈

9.2 常见问题

问题 解决方案
加载慢 减少外部资源
样式错乱 使用内联样式
交互失效 检查JS代码
截图空白 等待加载完成

10. 总结

10.1 核心要点

要点 说明
HTML展示 使用 present + html 参数
URL展示 使用 present + url 参数
脚本执行 使用 eval 执行 JS
截图获取 使用 snapshot 获取图像

10.2 下一步

  • 第52篇:OpenClaw Canvas 导航:URL 加载与控制
  • 第53篇:OpenClaw Canvas 执行:JavaScript 注入实战

参考资料

相关推荐
Litluecat3 小时前
2026年7月24日科技热点新闻
人工智能·科技·新闻·每日·速览
SharpCJ3 小时前
在 JetBrains IDE 中接入 OpenCode 并配置自定义模型
ai·aigc
用户8181870627463 小时前
第6章 thinkingLevel 思维层级体系
人工智能
熙丫 133814823864 小时前
人工智能训练工程师考试报名2026:报考条件、报名入口及注意事项
人工智能
凡情4 小时前
dify 图片提取文字
人工智能
JaydenAI4 小时前
[AG-UI详解-06]AG-UI针对MAF的服务端实现
ai·agent·ag-ui·maf
恒知学术4 小时前
SCI 文献怎么检索?英文关键词、DOI、被引量和开放获取线索整理
人工智能·深度学习·sci·文献检索·谷歌学术·doi
greatonce4 小时前
巨益及核全球电商业财一体化方案 | 行业能力概览
人工智能
中微极客4 小时前
Veo视频生成与Gemini Agent平台集成实践
数据库·人工智能·oracle·音视频