使用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] }]
  }
}
相关推荐
阿伟来咯~14 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端19 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱22 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai31 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨32 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js