背景
由于项目首页上需要大量的图表,大概超过100张复杂的图表,复杂的图表,并且有一个三维的地图展示,这个对于浏览器展示的压力非常大,测试时普通的机子都无法正常展示图片。
环境
页面上的图表大部分都是基于Echarts图表绘制的,有动效,最终绘制的图片应该是canvas。
三维的地图是用WebGl渲染的。针对这些图,我们暂时处理办法是把绘制图表的图表作为图片来展示,减轻客户端的压力
OK,有思路了,接下来具体怎么办
寻找后台可用的截图工具
功能比较
工具 | 优点 | 缺点 | 开发商 |
---|---|---|---|
phantomjs | phantom利用的是webKit内核,全面支持web而不需浏览器支持,快速,原生支持各种Web标准。 速度快,使用简单。 | 现在这个项目属于冻结状态,无人维护,现在2.1版本不支持flex布局,2.5只有beta版本的。这是官方的说法 | Ariya Hidayat 两名开发者 |
puppeteer | 类似于PhantomJS,但Puppeteer是Chrome官方团队进行维护的,前景更好 | 安装过程中在国内需要依赖google的服务,可能无法访问 | 谷歌官方 |
html2canves | 前台技术,实现比较容易。 | 无法后台操作,对浏览器有要求 | niklasvh |
html2image | 纯java实现。 | 需要多线程的支持 | niklasvh |
综合上面的比较和官方的示例,应该是phantomjs和puppeteer两个方便使用下面来照着官方的示例简单的写一个
package.json
{
"name": "demos",
"version": "0.0.1",
"dependencies": {
"capturejs": "^0.3.0",
"debug": "~2.2.0",
"puppeteer": "1.9.0",
"qiniu": "^6.1.10",
"system": "^1.0.4",
"webpage": "^0.3.0"
}
}
截图1080p的核心代码
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://echarts.baidu.com/examples/');
page.setViewport({width:1920*1,height:1080*1});
let path = 'example.png';
await page.screenshot({path: path,fullPage:true});
await browser.close();
})();
这么设置后,初次下载还可以,后来把图片的分辨率设置为8k分辨率,这时候有的截图就没有下载全
通过添加页面加载完毕解决问题
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://echarts.baidu.com/examples/',{waitUntil :"load|domcontentloaded|networkidle2",timeout:300000});
page.setViewport({width:1920*1,height:1080*1});
let path = 'example.png';
await page.screenshot({path: path,fullPage:true});
await browser.close();
})();
后来发现截的图跟预设的效果不一致,不是透明的,需要设置透明属性,最终修改完毕如下
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
page._emulationManager._client.send(
'Emulation.setDefaultBackgroundColorOverride',
{ color: { r: 0, g: 0, b: 0, a: 0 } }
);
await page.goto('http://echarts.baidu.com/examples/',{waitUntil :"load|domcontentloaded|networkidle2",timeout:300000});
page.setViewport({width:1920*1,height:1080*1});
let path = 'example.png';
await page.screenshot({path: path,fullPage:true});
await browser.close();
})();
到此所有问题都已经解决