使用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] }]
  }
}
相关推荐
QGC二次开发5 分钟前
Vue3 : Pinia的性质与作用
前端·javascript·vue.js·typescript·前端框架·vue
云草桑16 分钟前
逆向工程 反编译 C# net core
前端·c#·反编译·逆向工程
布丁椰奶冻21 分钟前
解决使用nvm管理node版本时提示npm下载失败的问题
前端·npm·node.js
Leyla1 小时前
【代码重构】好的重构与坏的重构
前端
影子落人间1 小时前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
世俗ˊ1 小时前
CSS入门笔记
前端·css·笔记
子非鱼9211 小时前
【前端】ES6:Set与Map
前端·javascript·es6
6230_1 小时前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人1 小时前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛2 小时前
HTML 揭秘:HTML 编码快速入门
前端·html