现在大部分系统图表的生成和包括打包下载依赖后端的报表服务,由于后端报表服务可定制化成都差,扩展困难,风格和样式单一,也很难做出炫酷的效果。本文讲述一下前端实现报表的批量打包下载。
实现过程
选择eCharts的理由:
(1)丰富的图表类型
(2)多个坐标系的支持
(3)丰富的api文档
(4)深度的交互式数据探索
(5)大数据量的展现
(6)多维数据的支持以及丰富的视觉编码手段
(7)动态数据
(8)绚丽的特效
(9)最重要的一点,好用还开源免费
eCharts安装和使用请查看官网或者github
需要注意的是:表头表尾插入图片logo等功能需要3.7.2及以上版本才能支持。
准备开始:
1、eChart制作图表
要实实现以上报表的展现,我首先去想到的是eCharts有没有表尾的配置,实际eCharts是没有的,但是他可以配置多个title,所以我通过配置两个title,控制title在报表的位置来实现表头表尾效果(页眉页脚也是一样的思路)。还有一个技术点是图标和样式应该怎么去实现,恰好eCharts在title标签内可以配置rich(图片的插入和自定义在新版本才会有,目前最新版本3.8.4,如果不支持的话请升级版本)
eCharts配置例子(因为一般的报表的表头表尾都有统一规则所以这我写的是一个公共的方法)
functiongetChartTitle(subtext, title, officeName){
return[{
left:30,
text: title,
textStyle: {height:28,fontSize:20,fontFamily: fontFamily,fontWeight:600},
subtext: subtext,
subtextStyle: {
left:30,
lineHeight:20,
fontSize:14,
fontFamily: fontFamily,// 自定义的字体
fontWeight:400,
rich: {lineHeight:30}
},
x:'10px',
y:'30px',
textAlign:'left'
}, {
text:''+""+''+''+'',
bottom:'20px',
z:2,
right:'-80px',
textAlign:'center',
textStyle: {
rich: {
a: {
height:20,
fontSize:14,
fontFamily: fontFamily,
fontWeight:400,
color:'#a9a9a9',
lineHeight:20,
padding: [3,4,5,6]
},
b: {backgroundColor: {image:'你的图片的base64或者Url'},height:18},c: {
height:20,
fontSize:14,
fontFamily: fontFamily,
fontWeight:400,
color:'#ed6c00',padding: [3,,5,6]
},x: {
height:20,
fontSize:14,
fontFamily: fontFamily,
fontWeight:400,
padding: [3,,5,6],
color:'#ececec'
}
}
}
}]
}
如果我们的下载就是所见即所得的eCharts的图表,那么我们只需要把每个图的eCharts的图的base64直接取到放到前端的数组里。如果我们看到的和下载的不一致的化,那我们就要考虑一个一个的去渲染图表,然后取到图表以后马上去销毁这个实力,为了页面的流畅程度,一个个加载取值然后销毁是一个必要操作。
经验告诉我们eCharts的实例如果单页超过10的话,会有明显卡顿感。来看一下,分步加载取图的代码。
functioninitDownChart(option, height){
varheight = height1500
varid = (newDate()).getTime()
$('#hide-visual').append('
')
varinstance = echarts.init(document.getElementById(id));
instance.setOption(option);
vardefer = $q.defer();
setTimeout(function(){
defer.resolve({
dataUrl: instance.getDataURL({
pixelRatio:1,
backgroundColor:'white'
})
})
instance.dispose();
$('#'+ id).remove();
},)
returndefer.promise;
}
注意:eCharts实例化必须要在有高度和宽度的容器。
2、将取到的图片压缩到zip并生成链接下载
使用的是zip.js来实现图片的压缩到zip,它本身自己的调用方法并不好用,因此我做了一层封装,以下是封装代码。
functioncreateTempFile(callback){
vartmpFilename ="tmp.zip";
requestFileSystem(window.EMPORARY,4*1024*1024*1024,function(filesystem){
functioncreate(){
filesystem.root.getFile(tmpFilename, {
create:true
},function(zipFile){
callback(zipFile);
});
}
filesystem.root.getFile(tmpFilename,null,function(entry){
entry.remove(create, create);
}, create);
});
}
functionaddFiles(files, options){
//调用addFiles的时候直接调用addFiles(files,,onAdd:function(file){}.....)
varaddIndex =;
functionnextFile(){
varfile = files[addIndex];
if(options.onAdd) {
options.onAdd(file)
}
zipWriter.add(file.name +'.png',newzip.Data64URIReader(file.dataUrl),function(){
addIndex++;
if(addIndex < files.length)
nextFile();
else
options.onEnd();
}, options.onprogress ? options.onprogress :'');
}
functioncreateZipWriter(){
zip.createWriter(writer,function(writer){
zipWriter = writer;
if(options.onInit) {
options.onInit();
}
nextFile();
}, onerror);
}
if(zipWriter)
nextFile();
elseif(creationMethod =="Blob") {
writer =newzip.BlobWriter();
createZipWriter();
}else{
createTempFile(function(fileEntry){
zipFileEntry = fileEntry;
writer =newzip.FileWriter(zipFileEntry);
createZipWriter();
});
}
}
functiongetBlobURL(callback){
zipWriter.close(function(blob){
varblobURL = URL.createObjectURL(blob);
callback(blobURL);
zipWriter =null;
});
}
functiongetBlob(callback){
zipWriter.close(callback);
}
注:Blob方式是通用的,通过文件流的方式压缩下载,requestFileSystem这种方式也是可以的,但是这种方式是操作本地文件的方式做的,本质是把生成的zip放到硬盘的缓存的临时文件中,然后调用浏览器自己的native api获取这个文件的流,然后下载。好处是不会占用过多系统内存,缺点是只有chrome目前是完美支持的。
iCourt
技术团队
想要更多了解我们或投稿,联系小编 :
领取专属 10元无门槛券
私享最新 技术干货