Bootstrap

Echarts分享

Echarts基础知识

介绍

        主要内容就是自己在项目中使用Echarts的基础表,比如:柱状图、饼图、折线图等的思路和心得,希望为熟练掌握Echarts的同学提供一些思路,也希望没有使用过Echats的同学可以快速入门!

目录

一、快速入门

  • 基础概念了解
  • 一个完整图表的实现构成
  • 简单的柱状图、饼图和折线图的实现

二、进阶内容

  • 一个原型或者设计图出来后的实现思路
  • 非常规柱状图
  • 非常规折线图
  • 非常规饼图
  • 其他图表
  • 一些整活

三、自适应

  • 图表自适应
  • 大屏自适应
  • 首页自适应

四、好用工具分享

  • Apache ECharts
  • MCCharts
  • 数据可视化技术分享论坛

正文

快速入门

1、基础概念
1)图表容器

一个图标容器对应一个实例对象,一个实例对象可以包括多个图标和坐标系(通过option描述)

<template>
   <div id="main" style="width: 600px;height:400px;"></div> 
</template>

    图表容器注意点:

  1. 单独一个容器,不允许嵌套。下面是错误示例:

<template>
   <div id="main" style="width: 600px;height:400px;">
      <div>
        我是不允许嵌套的!
      </div>
   </div> 
</template>

2.需要给的一个唯一标识id。

3.必须给容器或者图标设置大小。以下为设置大小的几种方式.

/*1、通过内联样式设置大小*/
<div id="main" style="width: 600px;height:400px;">

/*2、通过id设置大小*/
#main{
  width:600px;
  height:400px;
}
/*3、单独设置图表大小(不希望图表大小跟容器大小一样)
  在初始化echarts实例时设置
*/
var myChart = echarts.init(document.getElementById('main'),null,{
   width:600,
   height:400
})

2) option

描述数据、数据如何映射成图形以及一些交互行为。通俗来讲就是描述对图表的需求,有什么数据、要画什么图表、图表长什么样子、有什么组件、组件能操作什么事件。

/*通常结构如下*/

var option = {
/*
基础配置:背景、文本样式、颜色主题
*/

/*
组件
*/

/*
数据
*/
}
myChart.setOption(option)
3) 组件

echarts配备了很多组件,其详细用法以及各种属性配置可以在官方文档–配置项手册中查看。常用的组件如下:

  • xAxis —— 直角坐标系X轴
  • yAxis —— 直角坐标系Y轴
  • grid —— 直角坐标系底板
  • tooltip —— 提示组件
  • serirs —— 系列
  • legend —— 图例组件
  • angleAxis —— 极坐标系角度轴
  • radiusAxis —— 极坐标系半径轴
  • polar —— 极坐标系底板
  • geo —— 地理坐标系
  • datazoom —— 数据区缩放组件
  • visualMap 视觉映射组件
4)series系列

series(系列)是数据以及数据呈现形式的集中体现。包括数值、图标类型以及其他关于数据如何映射成图的参数等。series可以为一个数组。

一个常见的series配置一般如下:


  series: [
          {
            name: 'xx',//series的标识
            type: 'bar',//类型可以为line(折线图)、bar(柱状图)、pie(饼图)、map(地图)等等
            textStyle:{
            
            }, //对一些文本样式的配置的参数bac
            backgroundColor:'xxx' //背景色
            data: [x,x,x,x,x,x,x,x]//要展示的数据
          }
        ]

2、一个完整图表的实现构成

在上面了解完基础概念之后,我们可以知道一个完整图标的构成如下:

Echarts结构图.png

3、简单柱状图、折线图、饼图的实现

实现步骤为:echarts的引入——容器的创建——实例的初始化——指定图表的配置项和数据——option设置。下面用一段完整代码举例。

<template>
<!-- step2:容器的创建 -->
    <div id="main" style="width: 600px;height:400px"></div>

</template>

<script>

//step1:引入echarts

import * as echarts from "echarts";

export default {

    data(){
        return{

        }
    },
    mounted(){
        this.initEcharts()
    },
    methods:{
        initEcharts(){
            //step3:实例的初始化           
            var myChart = echarts.init(document.getElementById('main'));
            //step4:指定图表的配置项和数据
            var option = {
              //标题组件  
              title:{
                text:'简单的柱状图'
              },
              //提示框组件
              tooptip:{
                position:['50%','50%']
              },
              //图例组件
              legend:{
                data:["图例1"]
              },
              //x轴组件
              xAxis:{
                data:['x1','x2','x3','x4']
              },
              //y轴组件
              yAxis:{
                axisTick:false
              },
              series: [
                {
                    name: '简单的柱状图',
                    type: 'bar',
                    data: [1, 2, 3, 4]
                }
              ]
            };
            //step5:option的生效设置
            myChart.setOption(option)
        }

    }
}

</script>
   

进阶内容

1、一个原型或者设计图出后的实现思路

如果比较熟悉echarts后,常规实现思路如下。如果不熟悉在原型或设计图出后也可以先参考一些现有案例(可以在线编程),再思考后面的内容。

未命名文件.png

2、非常规柱状图
1) 柱状图的背景

   实现效果如下:

image.png

实现方式:

方式一
//直接在series中设置
series:[{
    type:"bar",
    barWidth:15,
    showBackground: true,
    backgroundStyle: {
    color: 'rgba(30, 71, 156, 0.35)',
    borderRadius: [30, 30, 30, 30]
    }
}

注:这种方式一般会设定最大值为背景长度

方式二
//使用两层柱状图的叠加
series:[
    //背景
    {
    type:"bar",
    barWidth:15,
    yAxisIndex:1,
    data:backgroundData
    },
    //数据
    {
    show:true,
    type:'bar',
    barWidth:15,
    z:2,
    data:chartData
    }
]

注:这种方式可以自定义设置背景的长度,但是相对比较复杂,如果没有对背景有特别要求直接用第一种方法就好。

思考

像前面那种每一行的单位度量都不一样的情况,用柱状图来实现真的好吗?

屏幕截图 2023-02-27 164953.png

答:在柱状图的逻辑中,同一坐标系内,数据越多肯定柱子就会越长,要想让不同单位,不同大小的背景条一样长,总归是不符合逻辑的。所以要设置很多坐标才能达到效果。
像这种情况,就不一定要用echart的图表。我们可以使用进度条来实现类似的效果。实现方式就是利用父子容器的背景色来实现。大家可以去网上了解一下。
总的来说就是,是否使用echarts要考虑其逻辑合理性。

2)滚动条

滚动条主要通过dataZoom的配置项以及js方法来实现

dataZoom:[
    {
    show:false,
    type:'slider',
    yAsixIndex:0,
    width:8,
    startValue:0,//从第一个开始
    endValue:end,//一次性展示end+1个
    }
]

// 自动滚动
function autoMove() {
    setInterval(() => {
        if (Number(option.dataZoom[0].endValue) === categoryData.length - 1) {
            option.dataZoom[0].endValue = end;
            option.dataZoom[0].startValue = 0;
        } else {
            option.dataZoom[0].endValue = option.dataZoom[0].endValue + 1;
            option.dataZoom[0].startValue = option.dataZoom[0].startValue + 1;
        }
        myChart.setOption(option);
    }, 3000);
}
autoMove();
myChart.off('click',autoMove()); 
myChart.on('click', clearInterval() );
3)立体

立体柱状图图一般都是通过图形的叠加来实现效果的。

思路:实现思路为:象形柱图(pictorialBar) + 柱状图(bar) + 象形柱图(pictorialBar)

注:象形柱图是可以设置各种巨像图形(图片、SVG、PathData等)的柱状图,用于至少一个类目轴或者时间轴的坐标系上。

立体柱状图.png

以下为举例:

series:[
{
name:"立体柱",
type:'bar',
barWidth:24,
barCategoryGap:12,
data:data
},
{
name:"立体柱",
type:'pictorialBar',
symbolSize:[24,6],
symbolOffset:[-31,-3] //这个属性决定了顶部是否跟柱子契合
z:12,
symbolPosition:'end',
data:data//值要与柱状图保持一致,值不对高度会对不上
},
{
name:"立体柱",
type:'pictorialBar',
symbolSize:[24,6],
symbolOffset:[-31,3] //这个属性决定了顶部是否跟柱子契合
z:12,
symbolPosition:'start',
data:data//这个值设置成大于0就可以,设这里position一定会在柱子底部展示
}
4)其他

其他的一些进阶内容,还包括了比如:多坐标轴(上下、左右展示等),数据排序,多种图表融合等等,大家在用到的时候,都可以去官网文档去查配置项。

3、非常规折线图
1)多折线

多折线问题非常常见,通常有多折线单轴、多折线多轴两种情况。

单轴
//单轴只需要legend与series中的name对应就可以了
legend:{
    data:['test1','test2']
},
series:[
    {
    name:'test1',
    type:'line',
    data:[1,2,3,4,5,6,7]
    },
    {
    name:'test2',
    type:'line',
    data:[7,7,7,7,7,7,7]
    },
]
多轴

例子:

image.png

//多轴要为series设置特定的坐标系

series:[
    {
    name:'test1',
    type:'line',
    yAxisIndex:0,//指定y轴
    data:[1,2,3,4,5,6,7]
    },
    {
    name:'test2',
    type:'line',
    yAxisIndex:1,//指定y轴
    data:[7,7,7,7,7,7,7]
    },
]

2)自定义指示器

可以通过设置自定义symbol来更换悬停时的拐点指示器。指示器的设置其实也很简单,但是由于echarts在自定义下载图标时,其不支持相对路径的写法,只支持网上地址,所以要用在线地址url或者base64的写法。

例子:
image.png

symbol:'image://base64地址'

base64在线转换地址

4、非常规饼图
1)环形图
普通环形图

image.png

series:[{
type:'pie',
center:['50%','50%'],
radius:['20%','30%'],//设置环形的宽度
data:[
    {
    'name':'一月',
    'value'80,
    },
    {
    'name':'二月',
    'value'20,
    }
 ]
带背景和圆角的环形图

实现方法可以通过极坐标+柱形图的方式实现

image.png

angleAxis:{
     max:total,
     axisLabel:false,
     axisTick:false,
     axisLine:false,
     splitLine:false
 },
 radiusAxis:{
     type:"category",
     data:["已经使用的资源","未使用的资源"],
     axisLabel:false,
     axisTick:false,
     axisLine:false
 },
 polor:{
     center:["50%","50%"],
     radius:["60%","80%"]
 },
 series:[
 {
    name:"name",
    type:"bar",
    coordinateSystem:"polar",
    barWidth: 10,
    showBackground: true,
    itemStyle: {
    color: color1,
    borderRadius: [4, 4, 4, 4],
    },
    backgroundStyle: {
    color: color2,
    },
    data: [used]
 }
2)多层环形图

目标效果:
image.png

要求:
1、内外层对应 2、悬停触发高亮和提示框,显示相应信息(label固定位置)3、点击下方图例,触发提示框显示相应信息。

思路:其实在刚看到这种多层的环形图的时候,第一眼想到的是使用旭日图,旭日图是多层的环形图组成,在数据结构上,内圈是外圈的父节点,内圈是外圈的父节点,既能像饼图一样体现局部和整体的占比,又能像树图一样表现层级关系。

就像这种:

image.png

但是如果使用旭日图虽然能达到很好的内外层联动,但是无法做到饼图的label和legend这么好的效果。所以我们后来还是用来饼图。

解决方法:

//内外层对应
只需要内外层的数据顺序对应就好了

//悬停触发高亮以及label
myChart.on('mouseover', function(params) {
 const unHighlightList = []
        //高亮判断
        for (const item in seriesData) {
          if (seriesData[item].name !== params.name)
          { unHighlightList.push(seriesData[item].name) }
        }
        myChart.dispatchAction({
          type: 'downplay',
          name: unHighlightList
        })
        //根据params.name获取label要展示的信息内容,并且每个模块设置单独的连线
         if (params.name === '长沙') {
          _this.cityName = '长株潭板块-' + params.name
          myChart.setOption({
            series: {
              name: '十三地市',
              labelLayout: {
                x: '73%',
                y: '30%'
              },

              data: seriesData
            }
          })
        }
        ....
//图例触发高亮以及label
    myChart.on('legendselectchanged', function(params) {
        const dowmplayList = []
        let item
        let regionName
        let labelLayoutX
        let labelLayoutY
        for (item in params.selected) {
          if (params.selected[item] === true) {
            dowmplayList.push(item)
          }
        }
        myChart.setOption({
          // animation: false,
          legend: { selected: { [params.name]: true }}
        })
        myChart.dispatchAction({
          type: 'downplay',
          name: dowmplayList
        })
        myChart.dispatchAction({
          type: 'highlight',
          name: params.name
        })
    }
5、其他图表
关系图

image.png

雷达图

image.png

树图

image.png

水球图

image.png

词云

image.png

一些整活
小游戏

这个游戏就是使用echarts的散点图和自定义系列来实现的,想了解可以看下面的链接。

项目地址,点击前往

image.png

下面这个游戏是通过热力图实现的"我的世界",有兴趣也可以了解一下

image.png
在线案例,点击前往

小工具

时钟是通过仪表盘实现的,想了解可以看下面的链接。

在线案例,点击前往

时钟.gif

绘画

下面这个图是使用echarts得关系图和折线图来实现得,有兴趣可以了解一下

在线案例,点击前往

画.gif

从上面几个案例可以看出echarts得功能还是很强的。但是有时由于封装得太好就会导致我们在做一些特制化得改动得时候不是那么容易。

自适应

因为涉及到不同屏幕分辨率,这就要求我们进行页面得自适应,来保证页面得布局不会变形。这里讲一下图表的自适应、大屏自适应、和首页自适应

图表自适应
//监听页面的 resize事件获取浏览器大小改变的事件,然后调用 echartsInstance.resize 改变图表的大小。注意不能把图标容器的宽高完全固定
var myChart =echarts.init(document.getElementById('main'));
    window.addEventListener('resize', function() {
    myChart.resize();
});
  
#main{
width:400px;
height:100%;
}
  
大屏自适应

大屏自适应我们常用的一般就是两种:一种是postcss-pxtorem 还有一种是SacleBox.在算力大脑这个项目中,我们两个大屏的自适应都是用scaleBox来写的,非常简单好用。

下面是较为详细的代码
点击前往

首页自适应

首页由于包含元素过多,并且涉及一些伸缩操作,再使用scaleBox效果就没那么好了。我们这里采用了固定高度+百分宽度+媒体控制来实现。实现效果如下:

首页自适应.gif

@media screen and (max-width: 1200px) {
/*
*样式设置
*/
}

@media screen and (max-width: 700px) {
/*
*样式设置
*/
}

好用工具分享

Apache ECharts

非常细、非常全,是最好用的工具。配置项手册里面有你想知道的一切。

image.png

官网地址

MCChart

MCCharts是我觉得第二好用的一个工具。里面有大量的Echarts案例,而且能够在线编辑,如果没什么头绪,可以来查找一些案例,或许可以为自己提供帮助。

官网地址

image.png

数据可视化技术分享论坛

这个论坛里也提供了很多可在线编辑的Echarts案例.(不能通过内网访问)

image.png

感谢大家的聆听!

;