Echarts生成canvas后转图片保存

Posted on 2021-08-29 17:12:37
Author: 可乐小可爱メ
1.背景

业务场景是 动态邮件报表(含各种echart图标) 定期发送不同人物;

    1.1 难点是 如何动态生成图形化报表图片插入到 email发送.

2. 解决思路

     两个方向解决:

        方法A: node-echarts 服务端绘制生成 保存到本地

        方法B: 客户端生成 转化 插入到email

3. 初探

    方法A 首先被排除, 

    node-charts 包 当前状态 1.1.4 • Public • Published 

    并且实际操作后, 确实如一些帖子分享所说 相关依赖安装失败。 暂时放弃

    方法B 的思路, 是基于已经有的PC项目(已通过echarts 有了相关图表),保存相关图标的 canvas到image, 然后 image 到服务器本地 然后 插入Email.

4. 技术方案

 

核心点是 通过  puppeteer 模拟访问获取.

5. 代码实现

    5.1 Node Server

const Express = require("express");
const request = require("request");
const app = new Express();

app.get("/", (req, res) => {
res.send("20001 server.");
});
app.get("/api", (req, res) => {
const { query } = req;
if (!query || !query.memberId) {
return res.json({ code: 10010, msg: "Request Error" });
}
// 模拟请求 Business Server
request(
{
url: "http://java.server.com/api" + query,
method: "xxx",
},
(err, response, data) => {
// 模拟数据返回
const option = {
title: {
text: "ECharts 入门示例",
},
tooltip: {},
legend: {
data: ["销量"],
},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
},
yAxis: {},
series: [
{
name: "销量",
type: "bar",
data: [5, 20, 36, 10, 10, 20],
},
],
};
if (err) {
// return res.json({
// code: 20010,
// msg: "JAVA Server Error",
// });
return res.json(option);
}
return res.json(data);
}
);
});

app.use("/static", Express.static("static"));

app.listen("20001", () => {
console.log("listen on: http://127.0.0.1:20001");
});

    5.2 Puppeteer.js

const puppeteer = require("puppeteer");
const target = "http://127.0.0.1:20001/static/?memberId=123";
const userAgent =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36";
puppeteer
.launch({
executablePath:
"C:\Program Files\Google\Chrome\Application\chrome.exe",
headless: false,
})
.then(async (browser) => {
const page = await browser.newPage();
page.setUserAgent(userAgent);
await page.goto(target);
await page.waitForSelector("button[title="save-btn"]").then(() => {
page.click("button[title="save-btn"]");
setTimeout(() => {
browser.close();
}, 2000);
});
});

    5.3 静态Html index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>canvas to image</title>
</head>

<body>
<div id="main" style="width: 600px; height: 400px"></div>
<button id="save-btn" title="save-btn">save</button>
</body>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.1.2/dist/echarts.min.js"></script>
<script type="text/javascript">
const xhr = new XMLHttpRequest();
const canvasWrap = document.getElementById("main");
const btn = document.getElementById("save-btn");
const { search } = window.location;
xhr.open("GET", "http://127.0.0.1:20001/api" + search);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
const option = JSON.parse(xhr.response);
const myChart = echarts.init(canvasWrap);
myChart.setOption(option);
}
};
xhr.send();

btn.onclick = function () {
const canvas = canvasWrap.getElementsByTagName("canvas")[0];
const fileName = "xxxxs.jpg";
const dataImg = new Image();
const imgData = canvas.toDataURL("image/jpg");
dataImg.src = imgData;
const blob = dataURLtoBlob(imgData);
const objurl = URL.createObjectURL(blob);
const alink = document.createElement("a");
alink.href = objurl;
alink.download = fileName;
alink.click();

function dataURLtoBlob(dataurl) {
const arr = dataurl.split(",");
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
};
</script>
</html>

    5.4 定时任务 crontab/node-schedule 请参考之前文章 Node.js 定时任务(node-schedule,pm2,shell脚本)

    5.5 业务接口(JAVA server)根据实际情况 返回当前要生成的 Echarts图标相关参数


6. 注意点

    6.1 以上是win环境代码, 实际到 centos后实测 需要修改 puppeteer.js 中 launch参数

.launch({
headless: false,
args: ["--no-sanbox"],
executablePath: "/usr/bin/chromium-browser",

})

 并且需要更换非root用户 启动puppeteer, 实际执行中 会报相关错误,


需要安装相关依赖 开启配置项。 CentOS解决xhost: unable to open display

    6.2 未完全解决问题    

    当前脚本执行通过log,确认没有报错, 执行完成。 但(centos中)找不到保存的文件




当前评论 (0) 登录后评论

暂无评论