使用Puppeteer生成echarts图片

Puppeteer简介

Puppeteer 是一个用于控制 Headless Chrome 或 Chromium 浏览器的 Node.js 库。它提供了一个高层次的 API,能够让你以编程方式操作浏览器,从而实现自动化任务,比如生成页面截图和 PDF、抓取网页内容、自动化表单提交、UI 测试等。

简单来讲我们部署一个虚拟浏览器, 通过后台渲染然后把图片输出

安装Puppeteer

使用node.js可以直接将Puppeteer部署为服务

bash 复制代码
mkdir puppeteer-service
cd puppeteer-service
npm init -y
npm install puppeteer
npm install express

编写js脚本

编写一个用于启动的js脚本, 起名 为indx.js, 将其放在根目录下

javascript 复制代码
const express = require('express');
const puppeteer = require('puppeteer');
const bodyParser = require('body-parser');
const fs = require('fs');
const path = require('path');

const app = express();
app.use(bodyParser.json());

app.post('/generate-echarts', async (req, res) => {
    const { templateName, data } = req.body;
	console.error('请求参数:', data);
    if (!templateName) {
        return res.status(400).send('缺少模板名称');
    }

    if (!data) {
        return res.status(400).send('缺少ECharts配置参数');
    }

    const templatePath = path.join(__dirname, 'templates', `${templateName}.html`);

    if (!fs.existsSync(templatePath)) {
        return res.status(404).send('模板文件不存在');
    }

    let browser;
    try {
        // 启动无头浏览器
        browser = await puppeteer.launch({ headless: true });
        const page = await browser.newPage();
        const content = fs.readFileSync(templatePath, 'utf-8');

        await page.setContent(content);

        // 等待 #chart 元素加载完成
        await page.waitForSelector('#chart', { timeout: 60000 });

        // 将配置参数传递给页面并渲染图表
        await page.evaluate(data => {
            window.postMessage(data, '*');
        }, data);

        // 等待 ECharts 动画完成
        await page.waitForFunction(
            () => window.chartRendered === true,
            { timeout: 60000 }
        );

        const element = await page.$('#chart');
        const boundingBox = await element.boundingBox();

        if (!boundingBox) {
            throw new Error('#chart 元素未能正确加载或未设置尺寸');
        }

        await page.setViewport({
            width: Math.ceil(boundingBox.width),
            height: Math.ceil(boundingBox.height)
        });

        const screenshotBuffer = await element.screenshot();

        res.setHeader('Content-Type', 'image/png');
        
        res.send(screenshotBuffer);
    } catch (error) {
        console.error('生成图表时出错:', error);
        res.status(500).send('生成图表时出错');
    } finally {
        if (browser) {
            await browser.close();
        }
    }
});

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Puppeteer 服务运行在端口 ${PORT}`);
});

echarts代码

首先创建一个templates文件夹放在根目录下, 然后我们把所有将来要用到生成图片的echarts的html文件放在这个目录下

我们可以再官网女随便找一个echarts图片来进行生成

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
</head>
<body>
    <div id="chart" style="width: 600px;height:400px;"></div>
    <script>
        // 使用传入的配置参数初始化 ECharts 图表
        function renderChart(option) {
            var chart = echarts.init(document.getElementById('chart'));
            chart.setOption(option);

            // 在所有动画完成后触发事件
            chart.on('finished', function () {
                console.log('ECharts animation finished');
                window.chartRendered = true;
            });
        }

        // 等待 Puppeteer 注入配置参数并渲染图表
        window.addEventListener('message', function (event) {
            renderChart(event.data);
        });
    </script>
</body>
</html>

启动服务

启动服务只需要在根目录下执行

bash 复制代码
node index.js

测试请求服务

使用postman请求:http://localhost:3000/generate-echarts

请求体:

bash 复制代码
{
  "templateName": "echart",
  "data": {
    "title": { "text": "动态 ECharts 示例" },
    "tooltip": {},
    "xAxis": { "data": ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"] },
    "yAxis": {},
    "series": [{ "name": "销量", "type": "bar", "data": [5, 20, 36, 10, 10, 20] }]
  }
}
相关推荐
2501_9400417414 小时前
应用构建:前端复杂交互与数据可视化的进阶之路
前端·信息可视化
前端若水14 小时前
项目初始化:Vite + React + shadcn/ui
前端·react.js·ui
ZC跨境爬虫14 小时前
模块化烹饪小程序开发日记 Day4:网络层基础设施与接口治理实践
前端·javascript·数据库·ui·html
冴羽yayujs14 小时前
快速夯实 JavaScrilpt 基础的 33 个概念
前端·javascript·github·前端开发
放下华子我只抽RuiKe514 小时前
React 从入门到生产(二):状态与事件处理
前端·人工智能·深度学习·react.js·机器学习·前端框架·github
Maimai1080814 小时前
React 项目目录结构怎么设计:从基础分层到真实业务落地
前端·javascript·react.js·microsoft·前端框架
开开心心就好14 小时前
带OCR识别的电子发票打印工具
运维·javascript·科技·游戏·青少年编程·ocr·powerpoint
Csvn14 小时前
CSS 技巧:移动端适配
前端
小茴香35314 小时前
大文件分片上传(前后端实现Vue+node.js)
前端·vue.js·node.js
Csvn14 小时前
前端技术 - 跨端方案对比
前端