Echarts的基本使用(待更新)

153 阅读9分钟

echarts是常用的一个画图工具,官网链接在这

1.Echarts的基本使用

最基本的Echarts使用需要用到两个方法,一个是echarts的方法init去初始化一个echarts实例myChart,然后就是实例的方法setOption,去给实例配置图表数据。我们这里创建一个基础的柱状图作为案例。

我们在使用Echarts画图的时候,需要去提前设置一个容器用来当作画板。

<template>
    <div class="screen-view">
        <div class="screen-header">
            <p>这里是Echarts组件的内容。</p>
        </div>
        <!-- Echarts容器 -->
        <div class="screen-container" id="chart">
        </div>
    </div>
</template>

一般为了方便获取到这个容器的DOM,所以我们会给他一个id值作为唯一标识。

然后我们就要引入echarts,当然要先下载 npm i echarts

引用完成以后,我们要先获取容器的DOM,然后用到echartsinit方法去初始化这个实例,接下来配置图表的数据。

图表的数据配置是很重要的,它决定了我们所画出来的图表是什么样子的,其中title属性是设置图表标题的,xAxis是用来设置横坐标都有哪些数据的,yAxis是配置纵坐标这里暂时用默认值就好所以直接是一个空对象{}series是配置图表的具体数据的,比如是什么类型的图,数据是多少。

最后通过实例方法setOption把这个图表的数据传入给实例就可以了。

import * as echarts from 'echarts';
export default {
    name: 'Echarts',
    data() {
        return {}
    },
    mounted() {
        // 初始化Echarts图表
        this.initChart();
    },
    methods: {
        initChart() {
            // 1.确保Echarts容器存在
            if (!document.getElementById('chart')) {
                return;
            }
            // 2.获取容器
            const chartDom = document.getElementById('chart');
            // 3.初始化Echarts实例
            const myChart = echarts.init(chartDom);
            // 4.设置图表配置项
            const option = {
                title: {
                    text: 'Echarts示例'  // 图表的名称
                },
                tooltip: {},
                xAxis: {
                    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']  // 横坐标的数据
                },
                yAxis: {}, // 默认可以不设置,纵坐标的数据会根据图表的具体数据去自适应
                series: [{  // 图表的具体数据也就是我们要展示的数据
                    name: '销量',  // 该数据的名称
                    type: 'bar',  // 该数据的类型  bar是指柱状图
                    data: [5, 20, 36, 10, 10, 20]  // 具体数据
                }]
            };
            // 5.使用配置项设置图表
            myChart.setOption(option);
        }
    },
}

效果如下:

ab421297-0014-49ce-a3ea-8aa847afddb4.png

完整代码如下:

<template>
    <div class="screen-view">
        <div class="screen-header">
            <p>这里是Echarts组件的内容。</p>
        </div>
        <!-- Echarts容器 -->
        <div class="screen-container" id="chart">
        </div>
    </div>
</template>
<script>
import * as echarts from 'echarts';
export default {
    name: 'Echarts',
    data() {
        return {}
    },
    mounted() {
        // 初始化Echarts图表
        this.initChart();
    },
    methods: {
        initChart() {
            // 确保Echarts容器存在
            if (!document.getElementById('chart')) {
                return;
            }
            // 获取容器
            const chartDom = document.getElementById('chart');
            // 初始化Echarts实例
            const myChart = echarts.init(chartDom);
            // 设置图表配置项
            const option = {
                title: {  // 图表名称
                    text: 'Echarts示例'
                },
                tooltip: {},
                xAxis: {  // x轴设置
                    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']  // x轴的值
                },
                yAxis: {},  // y轴设置
                series: [{  // 数据设置
                    name: '销量',
                    type: 'bar',
                    data: [5, 20, 36, 10, 10, 20]
                }]
            };
            // 使用配置项设置图表
            myChart.setOption(option);
        }
    },
}
</script>
<style lang='scss' scoped>
.screen-view {
    width: 100%;
    height: 100%;
    padding: 10px;
    box-sizing: border-box;

    .screen-header {
        height: 50px;
        line-height: 50px;
        text-align: center;
        font-size: 18px;
        margin-bottom: 10px;
    }

    .screen-container {
        width: 100%;
        height: calc(100% - 60px);
        padding: 10px;
        box-sizing: border-box;
    }
}
</style>

2.窗口的缩放对Echarts的影响

刚才只是Echarts的最基本使用,效果是可以实现的,但是如果我们把窗口给放大或者缩小呢?会不会对图有影响?

我们把窗口放大或者缩小试试看:

动画.gif

会发现在我们放大或者缩小窗口的时候,我们的DOM容器是会跟着变化的,但是图不会随着改变,没有达到自适应的效果,这体验肯定是不好的,所以我们这里还要用到echarts实例的一个方法resize

我们创建完实例以后,可以用js方法去监听窗口的变化,然后调用resize方法去改变图的大小。

// 5.使用配置项设置图表
myChart.setOption(option);
// 6.监听窗口大小变化,调整图表大小
window.addEventListener('resize', () => {
    myChart.resize();
});

动画.gif

3.柱状图叠加功能

柱状图的叠加功能就是在每个横坐标有多个柱状图的时候,将柱状图叠加在一个柱状图上面进行展示。这一点主要通过stack属性去实现,每个数据里面stack值相同的会叠加在一起。

xAxis: [
    {
        data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    },
],
yAxis: [
    {
        type: 'value',
        name: '单位:个',
    }
],
series: [ // 设置多个柱状图
    {
        name: '苹果',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20],
        label: {
            show: true,
        },
        stack: '1', // stack相同的会叠加在一起
    },
    {
        name: '香蕉',
        type: 'bar',
        data: [13, 21, 5, 43, 33, 18],
        label: {
            show: true,
        },
        stack: '1',  // stack相同的会叠加在一起
    },
]

动画.gif

当然如果stack的值不相同,那就不会叠加在一块。

series: [ // 设置多个柱状图
    {
        name: '苹果',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20],
        label: {
            show: true,
        },
        stack: '1',
    },
    {
        name: '香蕉',
        type: 'bar',
        data: [13, 21, 5, 43, 33, 18],
        label: {
            show: true,
        },
        stack: '1',
    },
    {
        name: '橙子',
        type: 'bar',
        data: [13, 21, 5, 43, 33, 18],
        label: {
            show: true,
        },
    },
]

image.png

还有一个stackStrategy属性,是选择什么情况可以叠加的,值有四个samesign只在要堆叠的值与当前累积的堆叠值具有相同的正负符号时才堆叠,all堆叠所有的值,positive只堆积正值,negative只堆叠负值,默认是samesign

那在这种默认的情况下,如果我们的数据的正负号不一样会出现什么情况。

series: [ // 设置多个柱状图
    {
        name: '苹果',
        type: 'bar',
        data: [5, 21, 36, 10, 10, 20],
        label: {
            show: true,
        },
        stack: '1',
    },
    {
        name: '香蕉',
        type: 'bar',
        data: [13, -20, 5, 43, 33, 18],  // 有一个数据和将要堆叠的数据正负号不一样  -20对应要堆叠的数据21
        label: {
            show: true,
        },
        stack: '1',
    },
]

image.png

可以看到此时这两个数据就没有堆叠,因为stackStrategy是默认值samesign,如果我们设置为all会怎么样。

series: [ // 设置多个柱状图
    {
        name: '苹果',
        type: 'bar',
        data: [5, 21, 36, 10, 10, 20],
        label: {
            show: true,
        },
        stack: '1',
    },
    {
        name: '香蕉',
        type: 'bar',
        data: [13, -20, 5, 43, 33, 18],  // 有一个数据和将要堆叠的数据正负号不一样  -20对应要堆叠的数据21
        label: {
            show: true,
        },
        stack: '1',
        stackStrategy: 'all', // 全部都堆叠
    },
]

动画.gif

可以看到显示的明显是有问题的,不过一般也不会这么设置因为没啥意义。

还有一个属性stackOrder是用于设置堆叠顺序的,默认是seriesAsc是指按照数据顺序堆叠,第一个数据在最下面,还有一个值是seriseDesc是反向堆叠。

折线图也可以堆叠,但是折线图堆叠起来没有柱状图比较直观所以用的比较少。

series: [
    {
        name: '苹果',
        type: 'line',
        data: [5, 21, 36, 10, 10, 20],
        label: {
            show: true,
        },
        stack: '1',
    },
    {
        name: '香蕉',
        type: 'line',
        data: [13, 20, 5, 43, 33, 18],
        label: {
            show: true,
        },
        stack: '1',
    },
]

image.png

4.tooltip框加滚动条

当如果我们曲线数据过多的时候就会出现tooltip框超出页面,用户就会体验不佳且数据展示不全,所以我们可以给tooltip框一个固定高度,然后再加上一个滚动条。

export function getLineOption(params) {
  let options = {
    legend: {
      top: 10,
      type: "scroll",
      width: "80%",
      right: 100,
    },
    tooltip: {
      trigger: "axis",
      axisPointer: {
        // 坐标轴指示器,坐标轴触发有效
        type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
      },
      enterable: true, // 鼠标是否可进入提示框浮层中
      hideDelay: 200, // 浮层隐藏的延迟
      confine: true,
      formatter: function (params) {
        var htmlStr =
          '<div style="height: auto;max-height: 240px;overflow-y: auto;"><p>' +
          params[0].axisValue +
          "</p>";
        for (var i = 0; i < params.length; i++) {
          htmlStr +=
            "<p>" +
            params[i].marker +
            params[i].seriesName +
            ":" +
            (params[i].value || "") +
            "</p>";
        }
        htmlStr += "</div>";
        return htmlStr;
      },
      textStyle: {
        fontSize: 12,
        color: "#fff",
      },
    },
    grid: [
      {
        top: 45,
        left: 50,
        right: 20,
        bottom: 30,
      },
    ],
    xAxis: [
      {
        type: "category",
        boundaryGap: true,
        data: params.xAxisData || [],
      },
    ],
    yAxis: [
      {
        type: "value",
        name: params.isZj ? "" : "单位: " + params.unit,
        axisTick: {
          show: true,
        },
        axisLine: {
          show: true,
        },
      },
    ],
    series: [],
  };
  let series = [];
  params.datas.forEach((item) => {
    series.push({
      name: item.text,
      data: item.valueList,
      type: "line",
      smooth: true,
      showSymbol: false,
    });
  });
  options.series = series;
  return options;
}

5.点击事件

1.常规点击事件

echarts中可以使用on方法为图形添加点击事件,但是这种方式添加的点击事件,只有点击在图形元素上才会触发事件处理函数。

代码如下:

<template>
  <div class="screen-view">
    <!-- 曲线图 -->
    <div class="chart" id="chart"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
export default {
  data() {
    return {
      myChart: null,
    };
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
    
      // 获取节点
      const el = document.getElementById("chart");

      // 准备echarts数据项
      let option = {
        backgroundColor: "transparent",
        tooltip: {
          trigger: "axis",
        },
        grid: [
          {
            top: 50,
            left: 40,
            right: 40,
            bottom: 20,
          },
        ],
        xAxis: [
          {
            type: "category",
            boundaryGap: false,
            data: ["1日", "2日", "3日", "4日", "5日", "6日", "7日"],
          },
        ],
        yAxis: [
          {
            name: "",
            type: "value",
          },
        ],
        series: [
          {
            name: "月亮",
            data: [4, 14, 18, 7, 9, 23, 11],
            type: "line",
          },
          {
            name: "MOON",
            data: [4, 14, 18, 7, 9, 23, 11],
            type: "bar",
          },
        ],
      };

      // 初始化echart
      if (el) {
        this.myChart = echarts.init(el);
        this.myChart.setOption(option);
      }

      // 先去除点击事件
      this.myChart.off('click')
       
      // 添加点击事件
      this.myChart.on("click", (params) => {
        // params里面有点击的曲线的相关信息,可以依此做一些操作
        console.log(params);
      });

      // 适应窗口
      window.addEventListener("resize",  () => {
        this.myChart.resize();
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.screen-view {
  padding: 10px;
  box-sizing: border-box;
  height: 100%;

  .chart {
    margin-top: 200px;
    margin-left: 200px;
    width: 800px;
    height: 500px;
    box-sizing: border-box;
    border: 1px solid #ccc;
  }
}
</style>

然后展示如下:

image.png

然后我们来点击一下试试看:

动画.gif

可以看到每次点击曲线的时候,就会触发点击事件,然后打印出相关信息,我们就可以通过这信息进行一些操作。

image.png

其中datavalue就是点击处曲线的数据,dataIndex就是点击处对应横坐标的索引,name就是点击处对应横坐标的名称,seriesIndex就是点击的曲线的索引,可以知道点击的第几条曲线,seriesName就是点击曲线的名称,seriesType就是点击曲线的类型是曲线图还是饼图还是柱状图。

这种方法有个缺点就是只有点击曲线的时候才会触发,下面的方法会让我们点击任意地方都能触发事件。

2.响应图形任意位置的点击事件

这种方法借助于convertFromPixel和zr来实现需要的效果,实现方法如下:

<template>
  <div class="screen-view">
    <!-- 曲线图 -->
    <div class="chart" id="chart"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
export default {
  data() {
    return {
      myChart: null,
    };
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      // 获取节点
      const el = document.getElementById("chart");

      // 准备echarts数据项
      let option = {
        backgroundColor: "transparent",
        tooltip: {
          trigger: "axis",
        },
        grid: [
          {
            top: 50,
            left: 40,
            right: 40,
            bottom: 20,
          },
        ],
        xAxis: [
          {
            type: "category",
            boundaryGap: false,
            data: ["1日", "2日", "3日", "4日", "5日", "6日", "7日"],
          },
        ],
        yAxis: [
          {
            name: "",
            type: "value",
          },
        ],
        series: [
          {
            name: "月亮",
            data: [4, 14, 18, 7, 9, 23, 11],
            type: "line",
          },
          {
            name: "MOON",
            data: [4, 14, 18, 7, 9, 23, 11],
            type: "bar",
          },
        ],
      };

      // 初始化echart
      if (el) {
        this.myChart = echarts.init(el);
        this.myChart.setOption(option);
      }
      
      // 先去除点击事件
      this.myChart.getZr().off('click')

      // 添加点击事件
      // 使用getZr添加图表的整个canvas区域的点击事件,并获取params携带的信息
      this.myChart.getZr().on("click", (params) => {
        // 获取到鼠标点击位置
        const pointInPixel = [params.offsetX, params.offsetY];
        // 使用containPixel API判断点击位置是否在显示图形区域
        if (this.myChart.containPixel("grid", pointInPixel)) {
          // 使用API convertFromPixel获取点击位置对应的x轴数据的索引值,
          let xIndex = this.myChart.convertFromPixel({ seriesIndex: 0 }, [
            params.offsetX,
            params.offsetY,
          ])[0];

          console.log(xIndex);
        }
      });

      // 适应窗口
      window.addEventListener("resize", () =>{
        this.myChart.resize();
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.screen-view {
  padding: 10px;
  box-sizing: border-box;
  height: 100%;

  .chart {
    margin-top: 200px;
    margin-left: 200px;
    width: 800px;
    height: 500px;
    box-sizing: border-box;
    border: 1px solid #ccc;
  }
}
</style>

动画.gif