# 图表实践二三事

一、echarts从demo到定制

1.步骤一

在echarts文档中心找与定制化相似的官网demo,依次为基础开始改造。

2.步骤二

先调整具有全局作用的一些属性,如颜色,总体排版布局等
1)如需要定制化的颜色,参考以下代码

setOption({
   ...
    /** 调色盘颜色列表 */
   color: ['#fb474b', '#fbca47', '#ca47fb'],
   ...
})

color字段数组颜色顺序和series字段每个系列的顺序是一一对应的。此全局作用后,坐标系里的类别颜色和对应的图例legend同时都变化完成。
2)调整图例legend位置等,参考以下代码:

setOption({
   ...
    /** 改变示例在图表的展示位置 */
   legend: {
          orient: 'horizontal', // 默认'horizontal'-水平, 'vertical'垂直(竖直)
          right: 'center', // 支持像素(px),百分比(%),或者'left', 'center', 'right'
          bottom: 0,
          width: '100%',
          itemGap: 15, // 每项之间的间隔
          /** 本例类别是官网demo最基础用到的类别 */
          data: ['邮件营销', '联盟广告', '视频广告']
        },
   ...
})

3)改坐标网格grid

setOption({
   ...
    /** 坐标网格 */
   grid: {
          left: '3%', // 默认 '10%'
          right: '4%', // 默认 '10%'
          top: '3%', // 默认 60px
          bottom: '10%', // 默认 60px,坐标离容器下侧的距离,支持像素(px),百分比(%)
          containLabel: true
        },
   ...
})

3.步骤三

1)修改tooltip,此配置非常灵活且复杂,以下仅一种示例参考

setOption({
   ...
    /** 坐标网格 */
   tooltip: {
          /** 'axis'-有类目的图(折线图,柱图),'item'-无类目图(散点图,饼图,雷达图等)*/
          trigger: 'axis',
          backgroundColor: 'rgba(255,255,255)', // 默认'rgba(50,50,50,0.7)'
          /** 提示框外框的额外样式,会有意外的惊或喜,可修改看看 */
          extraCssText: 'box-shadow:0px 2px 8px 0px rgba(0,0,0,0.15)',
          /** 内容的文字样式配置 */
          textStyle: {
            color: 'rgba(0,0,0,0.65)', // 默认 '#fff'
            fontSize: 12 // 默认14
          },
          /** 提示框内容展示修改 === 主要想修改marker的大小,不需要时就不用如此麻烦====
           * 模板型(使用模板,marker无法展示,所以既想修改格式又想保留marker,需函数回调方式)
           * formatter: '{b0}: {c0}<br />{b1}: {c1}'
           * 模板变量有 {a}, {b},{c},{d},{e},数字代表系列series中的索引
           * 折线(区域)图、柱状(条形)图、K线图 : {a}(系列名称),{b}(类目值),{c}(数值), {d}(无)
           * 散点图(气泡)图 : {a}(系列名称),{b}(数据名称),{c}(数值数组), {d}(无)
           * 地图 : {a}(系列名称),{b}(区域名称),{c}(合并数值), {d}(无)
           * 饼图、仪表盘、漏斗图: {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
           * {@xxx}:数据中名为'xxx'的维度的值,如{@product}表示名为'product'` 的维度的值。
           * {@[n]}:数据中维度n的值,如{@[3]}` 表示维度 3 的值,从 0 开始计数。
           * 可参考官网 label.formatter
           */
          formatter: (params) => {
            var result = ''
            params.forEach((item, index) => {
              // console.log(item)
              const cur_marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' + item.color + '"></span>'
              const title = index === 0 ? item.axisValue + '</br>' : ''
              result += title + cur_marker + item.seriesName + ':' + item.data + '</br>'
            })
            return result
          },
          /** 坐标轴指示器(grid里悬浮后显示的坐标十字架),柱状图一般为阴影
           *  简单场景此处用,xAxis或yAxis的axisPointer可覆盖此处配置
           */
          axisPointer: {
            /** 'line'-直线;'shadow'-阴影(柱状图用的较多);'none'-无;'cross'-启用指示器(十字),即x轴y轴都启用*/
            type: 'cross',
            lineStyle: {
              type: 'dashed',
              // 红色
              color: '#ff7200'
            }
          }
        },
   ...
})

2)修改坐标轴指示线(grid中悬浮展示的线或阴影),上例tooltip里面修改是方法之一,以下展示在坐标轴上修改的方法
2.1)x轴修改

setOption({
   ...
    /** x轴坐标 */
   xAxis: {
          type: 'category',
          boundaryGap: false,
          /** 官网demo一样的data值 */
          data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
          /** 如果x轴或者y轴某一轴设置了一个字段,另一轴这个字段会填充echart默认值,并有各字段权重不一样的情况 */
          axisPointer: {
            /** 标线出现时,轴上标签文案(各轴对应的值) */
            label: {
              show: true
            }
          }
        },
   ...
})

2.2)y轴修改

setOption({
   ...
    /** y轴 */
    yAxis: {
          type: 'value',
          /** 此处设置后,相同api字段就会覆盖tooltip中的axisPointer */
          axisPointer: {
            /** yAxis或xAxis时,类型比tooltip少,即不存在cross */
            type: 'line',
            // 轴标签
            label: {
              show: true, // 默认false
              precision: 'auto', // 小数点精度,如2
              /** 其他还有很多style属性参看官网 */
              color: '#333', // 默认 #fff
              backgroundColor: 'none' // 默认和lineStyle.color 的设置相同
            },
            lineStyle: {
              type: 'solid',
              // 颜色
              color: '#ca47fb'
            }
          }
        },
   ...
})

4.步骤四

系列series的定制化
1)线->每个类别的类型定义,线样式

setOption({
   ...
    /** 每个类别的样式、类型等设置 */
   series: [
          {
            name: '邮件营销',
            /** 简单图'line'-线;'bar'-柱;'pie'-饼;'scatter'-散点;
             * 复杂图设置类型对应的X轴或Y轴的字段也需要结合调整,防止误导,不在此赘述
             */
            type: 'line',
            /** 点图案:'emptyCircle'-空心圆(默认)'circle'-实心圆, 'rect'-方块, 'roundRect'-圆角方块,
             * 'triangle'-三角形, 'diamond'-菱形, 'pin'-大头针形(像定位标记图标), 'arrow'-小飞机, 'none' */
            symbol: 'circle',
            /** 点大小 */
            // symbolSize: 6,
            // symbolSize: [10,6], // 宽10,高6
            symbolSize: (value, params) => { // value-'data'数组的当前值,params-相关数据项参数,打印自行查看哪些有用
              console.log(value)
              const size = params.dataIndex < 3 ? 6 : 9
              return size
            },
            symbolRotate: 90, // 旋转角度,当为'arrow'时是小飞机切线角度的旋转
            connectNulls: false, // 是否连接空数据(null),默认true
            /** 是否平滑 */
            smooth: true,
            symbolOffset: [0, '50%'], // 相对原位置的偏移 下移一半
            hoverAnimation: false, // 悬浮 拐点动画 默认true(图标变大,闪一下)
            legendHoverLink: false, // 悬浮图例时,点线变粗变大,false-关闭,true-开启(默认)
            /** 同个类目('总量'),后一个系列的值会在前一个系列的值上相加 */
            stack: '总量',
            data: [120, 132, 101, 134, 90, 230, 210],
            /** 区域填充(面积图需要使用) */
            areaStyle: {
              /** 支持rgb rgba 十六进制 (渐变 径向渐变写法不同参考官网)  */
              color: '#fb474b',
              opacity: 0.2
            },
            lineStyle: {
              // 线条宽度
              width: 1.5
            }
          }
        ],
   ...
})

2)柱->每个类别的类型定义,柱样式

setOption({
   ...
    /** 坐标网格 */
    series: [{
          name: '邮件营销',
          type: 'bar',
          /** 图例悬浮 柱图高亮(如果有颜色替换,这个效果好像就没了) */
          legendHoverLink: true,
          itemStyle: { // ---图形形状
            /**  方法二 */
            // color: 'blue',
            // 圆角半径 只支持px
            barBorderRadius: [49, 49, 0, 0],
            /** 描边 宽度,默认不描边,所以borderType borderColor要在设置了borderWidth之后才会生效 */
            borderWidth: 2,
            /** 柱条的描边 'solid', 'dashed', 'dotted'*/
            borderType: 'solid',
            borderColor: '#477efb'

          },
          /** 柱宽 50(绝对像素px) '50%'(自适应宽度) */
          barWidth: '50%',
          data: [120, 132, 101, 134, 90, 230, 210]
        }],
   ...
})

二、echarts双Y轴

从单Y轴变双Y轴,有2个关键点:

setOption({
   ...
   /** 数组配置Y轴字段*/
    yAxis: [{
          type: 'value',
        },{
          type: 'value',
        }],
   series:[{
         ...
         /** 指定本数据放在哪个Y轴 */
         yAxisIndex: 0,
         ...
       },{
         ...
         yAxisIndex: 1,
         ...
       }]
   ...
})

剩余细节处理:1)左右两Y轴刻度线总数一致时,两边数值差距较大,需要自行处理刻度间距(动态计算更新配置),2)刻度数值小数点数量级的处理,最好到整数

双Y的示例,参考另一篇专篇

三:vue中使用echarts的踩坑点记录

1.首次init放在动态获取之后,直接调用会报错,需要延时处理
15928044232537
正确处理:

methods: {
    getData() {
        /** 总之此处是异步请求接口的一个结果(可以是封装后的,也可以是直接调的) */
        axios.get('/user?ID=12345')
          .then((response)=> {
            /** $nextTick 关键,不可少 */
            this.$nextTick(()=>{
              this.initEchart(response)
            })
          })
    },
    initEchart(data) {
        // divContainer为dom元素
        const divContainer = this.$refs.a
        const b = echarts.init(divContainer)
    }
}

2.动态化series,图表有缓存
正确处理:

methods: {
    initEchart() {
        const divContainer = this.$refs.a
        const myChart = echarts.init(divContainer);
        /** 关键 */
         myChart.clear();
         const seriesArr = handleSeries()
         myChart.setOption()
    },
    handleSeries() {
        let seriesArr = [];
        [1,2].forEach(item => {
            seriesArr.push({
                // 省略
                ...
            })
        })
        return seriesArr
    }
}

总结

echarts总体上手简单,生态良性。简单图表自己需要更改的就不用太多,实践起来方便,绝对可以为他转身。