一、echarts内置导出

众所周知,echarts是有专门的工具栏可以帮助我们导出图片的,就是我们的toolBox工具栏配置项,其内置导出图片数据视图动态类型切换数据区域缩放重置五个工具。

既然ehcarts都提供了这么丰富的工具栏,那俺为啥还要大费周章呢(摸鱼它不香嘛)🤔

  1. 导出图片的样式不能自定义,虽然它支持更改图标以及更改颜色,但却不符合咱项目的UI设计/(ㄒoㄒ)/~~。

  2. 产品要求导出图片时图片能大一点,不要跟页面的布局一样小小的。

  3. 当出现dataZoom数据缩放的滚动条时,用户滚动后再点击导出图片,是只能看到当前的缩放后的echarts图片滴。

  4. toolBox - saveAsImage配置项中有一个excludeComponents的属性,可以忽略导出图片的组件(看到这个真给我高兴坏了😍),结果一设置才知道,确实是忽略掉了dataZoom滚动条,但导出时还是滚动缩放后的echarts图片😅。

SO!!基于上述条件,咱不得不开始水(bushi)这篇文章了。

二、初步探索

  • first of all,居然echarts有导出图片的功能,那会不会有对应导出图片的API ?!

    事不宜迟,马上度娘->echarts->文档->API

    果然echarts实例化后提供一个getDataURL()的方法,里面可自定义导出格式,导出分辨率,导出图片背景色,以及可以选择导出时忽略echarts组件的图片。

(opts: {
    // 导出的格式,可选 png, jpg, svg
    // 注意:png, jpg 只有在 canvas 渲染器的时候可使用,svg 只有在使用 svg 渲染器的时候可用
    type?: string,
    // 导出的图片分辨率比例,默认为 1。
    pixelRatio?: number,
    // 导出的图片背景色,默认使用 option 里的 backgroundColor
    backgroundColor?: string,
    // 忽略组件的列表,例如要忽略 toolbox 就是 ['toolbox']
    excludeComponents?: Array.<string>
}) => string

  • second,解决用户拖拉滚动条,导致导出图片数据不全的问题。

    这个easy,直接新创建一个画布,再拿到当前echarts的配置项,创建一个echarts对象,再通过getDataURL()这个方法不就美滋滋的解决了嘛。

    顺便还将导出图片大小的问题解决了,唔~~~


三、代码实现初实现

俗话说的好,don‘bb show me your code

   
export async function exportEchartsImg(chart, imgOption = {}) {
      // 创建画布元素
      let canvas = document.createElement("canvas");
      canvas.width = imgOption.chartWidth || chart.getWidth();
      canvas.height = imgOption.chartHeight || chart.getHeight();

      // 创建 ECharts 实例并绑定到容器
      let myChart = echarts.init(canvas);
      let option = JSON.parse(JSON.stringify(chart.getOption()));

      // 修改图表配置项,
      option.dataZoom = [];

      myChart.setOption(option);

      // echarts的API方法:getDataURL() 获取图片
      let imageData = await myChart.getDataURL({
        type: "png",
        pixelRatio: 1,
        excludeComponents: ["toolbox", "dataZoom"],
      });
      // 创建链接元素并下载图片
      let link = document.createElement("a");
      link.href = imageData
      link.download = imgOption.imgName || "chart.png";
      link.click();

      // 释放资源
      canvas.remove();
      link.remove();
    },

我直接一个导出

我图呢!?!?我柱子呢!?

四、问题解决

GPT启动!! 百度启动!!

在我不断尝试gpt输出的答案之后,我看到了这一幕

  • 根据我实习‘两年半’的经验,我发现既然柱状图的label属性和数据都已经渲染上去了,那不应该柱子没有啊,难道是因为这个动画的原因,导致我的柱子并没有出现?!

  • 说时迟那时快,通过我不断的‘走访调查’后发现,ECharts 是默认使用动画效果来进行图表的异步渲染的,这就可能会导致当我init完echarts之后,直接调用getDataURL()柱状图的动画效果并没有渲染完毕。

1. 解决方法

  1. 我直接一个animation:false取消掉动画的渐变渲染过程,让其返璞归真,展示它最纯真的一面。

  2. 调用echarts API中的finished方法:渲染完成事件,当渲染完毕后再调用getDataURL()的方法获取图片。

五、最终代码

export async function exportEchartsImg(chart, imgOption = {}) {
      // 创建画布元素
      let canvas = document.createElement("canvas");
      canvas.width = imgOption.chartWidth || chart.getWidth();
      canvas.height = imgOption.chartHeight || chart.getHeight();

      // 创建 ECharts 实例并绑定到容器
      let myChart = echarts.init(canvas);
      let option = JSON.parse(JSON.stringify(chart.getOption()));

      // 修改图表配置项,
      this.modifyChartOption(option);  //自己定义个方法,对option进行一些操作,展示出你想要的导出图片的样子

      myChart.setOption(option);

      // echarts的API方法:getDataURL() 获取图片
      let imageData = await myChart.getDataURL({
        type: "png",
        pixelRatio: 1,
        excludeComponents: ["toolbox", "dataZoom"],
      });
      // 创建链接元素并下载图片
      let link = document.createElement("a");
      link.href = imageData
      link.download = imgOption.imgName || "chart.png";
      link.click();

      // 释放资源
      canvas.remove();
      link.remove();
    },

  modifyChartOption(option){
      option.dataZoom = [];
     // 将图表配置series中的animation去掉,防止导出图片时动画没开始 数据没渲染
      option.series.forEach((element) => {
        element["animation"] = false;    
        element.label["color"] = "#000";
      });
      option.xAxis.forEach((item) => {
        item.axisLabel["color"] = "#494949";
      });
      option.yAxis.forEach((item) => {
        item.axisLabel["color"] = "#494949";
      });
    }

六、ending

望你我都能在茫茫人海中找到那属于自己的星光,用坚定的步伐走向理想的彼岸,不负韶华的光阴。✨