最近公司有一个在线自动生成word文件并下载的功能,其中word中包含一些echarts的图表,并且这些截图是根据后台数据实时生成的,因为这个word是在后台用PHP生成的,并没有浏览器渲染echarts图标。经过一番探索最终利用Node结合Puppeteer在服务端成功渲染出echarts图表并插入word,下面给大家详细介绍下整个过程:
首先echarts的图表渲染需要js的执行环境,既然没有浏览器的参与,首先想到的就是Node的执行环境。经过一番搜索结合echarts官方关于服务器端渲染推荐的社区方案。终于发现Puppeteer这个好东西。
先来解释下Puppeteer是个什么东西。Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,用来模拟 Chrome 浏览器的运行。也就是说他就相当于一个浏览器。
直接上代码:
const puppeteer = require('puppeteer')
//定义通用函数
const render = async (options, imagePath) => {
// 创建浏览器实例
const browser = await puppeteer.launch({
args: ['--no-sandbox']
// headless: false
})
// 创建page对象
const page = await browser.newPage()
// await page.setViewport({ width: 1920, height: 1080 })
// 设置page内容
const containerElement = '<div id="container" style="width: 1200px;height:800px;"></div>'
const content = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>chart</title>
</head>
<body>
${containerElement}
</body>
</html>`
await page.setContent(content)
// 传递options对象到evaluate函数中,挂载到window对象的全局属性中
await page.evaluate((options) => {
window.chart = {
options: options
}
}, options, imagePath)
// 这里以百度echarts为例说明 ,注入echarts库到页面 这个也是有顺序的
await page.addScriptTag({
path: '../../../node_modules/echarts/dist/echarts.min.js'
})
await page.addScriptTag({
path: '../../../node_modules/echarts-wordcloud/dist/echarts-wordcloud.min.js'
})
// echarts 初始化脚本注入页面
await page.addScriptTag({
path: '/Users/sower/www/node/serverchart/world.js' //echarts插件的路径
})
await page.addScriptTag({
content: `
(function (window) {
let option =window.chart.options;
var myChart = window.echarts.init(document.getElementById('container'), null, {
renderer: 'svg'
});
myChart.setOption(option);
})(this);`
})
await page.waitFor(1000) // 停留一秒,否则有可能图表还没渲染完就截图
const $el = await page.waitForSelector('#container')
await $el.screenshot({ type: 'png', path: 'echarts.png' }) //开始截图
await page.close()
await browser.close()
}
//echarts option的内容 支持大部分的图表
var latlong = {}
latlong.AD = { latitude: 42.5, longitude: 1.5 }
latlong.AE = { latitude: 24, longitude: 54 }
latlong.AF = { latitude: 33, longitude: 65 }
latlong.AG = { latitude: 17.05, longitude: -61.8 }
latlong.AI = { latitude: 18.25, longitude: -63.1667 }
latlong.AL = { latitude: 41, longitude: 20 }
latlong.AM = { latitude: 40, longitude: 45 }
latlong.AN = { latitude: 12.25, longitude: -68.75 }
latlong.AO = { latitude: -12.5, longitude: 18.5 }
latlong.AP = { latitude: 35, longitude: 105 }
latlong.AQ = { latitude: -90, longitude: 0 }
latlong.AR = { latitude: -34, longitude: -64 }
latlong.AS = { latitude: -14.3333, longitude: -170 }
latlong.AT = { latitude: 47.3333, longitude: 13.3333 }
latlong.AU = { latitude: -27, longitude: 133 }
latlong.AW = { latitude: 12.5, longitude: -69.9667 }
latlong.AZ = { latitude: 40.5, longitude: 47.5 }
latlong.BA = { latitude: 44, longitude: 18 }
latlong.BB = { latitude: 13.1667, longitude: -59.5333 }
latlong.BD = { latitude: 24, longitude: 90 }
latlong.BE = { latitude: 50.8333, longitude: 4 }
latlong.BF = { latitude: 13, longitude: -2 }
latlong.BG = { latitude: 43, longitude: 25 }
latlong.BH = { latitude: 26, longitude: 50.55 }
latlong.BI = { latitude: -3.5, longitude: 30 }
latlong.BJ = { latitude: 9.5, longitude: 2.25 }
latlong.BM = { latitude: 32.3333, longitude: -64.75 }
latlong.BN = { latitude: 4.5, longitude: 114.6667 }
latlong.BO = { latitude: -17, longitude: -65 }
latlong.BR = { latitude: -10, longitude: -55 }
latlong.BS = { latitude: 24.25, longitude: -76 }
latlong.BT = { latitude: 27.5, longitude: 90.5 }
latlong.BV = { latitude: -54.4333, longitude: 3.4 }
latlong.BW = { latitude: -22, longitude: 24 }
latlong.BY = { latitude: 53, longitude: 28 }
latlong.BZ = { latitude: 17.25, longitude: -88.75 }
latlong.CA = { latitude: 54, longitude: -100 }
latlong.CC = { latitude: -12.5, longitude: 96.8333 }
latlong.CD = { latitude: 0, longitude: 25 }
latlong.CF = { latitude: 7, longitude: 21 }
latlong.CG = { latitude: -1, longitude: 15 }
latlong.CH = { latitude: 47, longitude: 8 }
latlong.CI = { latitude: 8, longitude: -5 }
latlong.CK = { latitude: -21.2333, longitude: -159.7667 }
latlong.CL = { latitude: -30, longitude: -71 }
latlong.CM = { latitude: 6, longitude: 12 }
latlong.CN = { latitude: 35, longitude: 105 }
latlong.CO = { latitude: 4, longitude: -72 }
latlong.CR = { latitude: 10, longitude: -84 }
latlong.CU = { latitude: 21.5, longitude: -80 }
latlong.CV = { latitude: 16, longitude: -24 }
latlong.CX = { latitude: -10.5, longitude: 105.6667 }
latlong.CY = { latitude: 35, longitude: 33 }
latlong.CZ = { latitude: 49.75, longitude: 15.5 }
latlong.DE = { latitude: 51, longitude: 9 }
latlong.DJ = { latitude: 11.5, longitude: 43 }
latlong.DK = { latitude: 56, longitude: 10 }
latlong.DM = { latitude: 15.4167, longitude: -61.3333 }
latlong.DO = { latitude: 19, longitude: -70.6667 }
latlong.DZ = { latitude: 28, longitude: 3 }
latlong.EC = { latitude: -2, longitude: -77.5 }
latlong.EE = { latitude: 59, longitude: 26 }
latlong.EG = { latitude: 27, longitude: 30 }
latlong.EH = { latitude: 24.5, longitude: -13 }
latlong.ER = { latitude: 15, longitude: 39 }
latlong.ES = { latitude: 40, longitude: -4 }
latlong.ET = { latitude: 8, longitude: 38 }
latlong.EU = { latitude: 47, longitude: 8 }
latlong.FI = { latitude: 62, longitude: 26 }
latlong.FJ = { latitude: -18, longitude: 175 }
latlong.FK = { latitude: -51.75, longitude: -59 }
latlong.FM = { latitude: 6.9167, longitude: 158.25 }
latlong.FO = { latitude: 62, longitude: -7 }
latlong.FR = { latitude: 46, longitude: 2 }
latlong.GA = { latitude: -1, longitude: 11.75 }
latlong.GB = { latitude: 54, longitude: -2 }
latlong.GD = { latitude: 12.1167, longitude: -61.6667 }
latlong.GE = { latitude: 42, longitude: 43.5 }
latlong.GF = { latitude: 4, longitude: -53 }
latlong.GH = { latitude: 8, longitude: -2 }
latlong.GI = { latitude: 36.1833, longitude: -5.3