vue3使用 echarts--柱状图x轴方向渐变色--日周月数据切换--echarts-api详解

639 阅读8分钟

前言

很多项目都会用到echarts,特别是做统计项目的时候,图表展现数据的形式确实更直接,echarts在很多时候能满足我们的需求,里面超级多的api,配置非常的灵活自由,但是不熟悉的时候容易不知道怎么配置,最近正好做了一个,来总结一下,大家有需要参考!

使用

项目框架

我们用的nuxt框架 vue3+nuxt3
nuxt框架 引入包的写法都是一样的

版本号

"nuxt": "3.0.0-rc.12"
"echarts": "5.1.2"

代码部分

1.下载包(如果不指定版本号就是最新版本的包)
npm install echarts@5.1.2 --save  
2.plugins文件夹创建echarts.ts文件,内容如下
import * as echarts from 'echarts/core'
import { GridComponent } from 'echarts/components'
import { LineChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'

echarts.use([GridComponent, LineChart, CanvasRenderer])

export default defineNuxtPlugin(nuxtApp => {
  return {
    provide: {
      echarts: echarts
    }
  }
})

3.在nuxt.config.js中配置插件(根据项目自身 不需要可不引入)
特别注意:nuxt3以上版本应该是不需要引入了,根据项目情况而定
plugins: [
  { src: "~/plugins/echarts.ts", ssr: false },
],
4.页面上使用

仅写了web的样式 h5需要的自己可以微调 图中切换M的时候颜色有点暗 可能看不太清
这个是由于两边渐变色值导致的 可以换 echarts.gif

<template>
  <div class="echarts-container">
    <div class="echarts-content-box">
      <div class="echarts-tab">
        <div 
        :class="echartVal == 'D' ? 'title-active title-day' : 'title-day'" 
        @click="changeEchart('D')"
        >D
        </div>
        <div 
        :class="echartVal == 'W' ? 'title-active title-week' : 'title-week'" 
        @click="changeEchart('W')"
        >W</div>
        <div 
        :class="echartVal == 'M' ? 'title-active title-mouth' : 'title-mouth'" 
        @click="changeEchart('M')"
        >M</div>
      </div>
      <div class="echarts-content">
        <div class="left">
          <span>24H</span><p>${{ Number(leftShowNum) == 0 ? 0 : leftShowNum }}</p>
        </div><div id="echartsBox" class="right"></div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import * as echarts from 'echarts'
import { defineComponent, computed, onMounted, ref } from 'vue'

export default defineComponent({
  setup() {
  //左侧展示的value值
    const leftShowNum = ref('')
  //日周月变量
    const echartVal = ref('D')
  //图表数据对象
    const echartDateObj: any = ref({})
    
    //判断是h5还是web
    function windowWidth() {
      var de = document.documentElement
      return self.innerWidth || (de && de.offsetWidth) || document.body.offsetWidth
    }
    
    onMounted(() => {
      setTimeout(() => {
        // if (windowWidth() < 750) {
        //h5
        // }else{}
        getEchartDate(40, 100, 16, 'vol', 'day')
      }, 100)
    })
    
    const changeEchart = val => {
      echartVal.value = val
      if (val == 'D') {
        getEchartDate(40, 100, 16, 'vol', 'day')
      } else if (val == 'W') {
        getEchartDate(30, 100, 30, 'vol', 'wek')
      } else if (val == 'M') {
        getEchartDate(20, 100, 40, 'vol', 'mon')
      }
    }
    
    const getEchartDate = async (val, num, width, title, date) => {
    //   const { data } = await fetch('数据接口')
      let list :any
      if (date=='day') {
        list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
          { 'num': '12', 'date': '2023-01-13T00:00:00Z' },
          { 'num': '3', 'date': '2023-01-14T00:00:00Z' },
          { 'num': '24', 'date': '2023-01-15T00:00:00Z' },
          { 'num': '15', 'date': '2023-01-16T00:00:00Z' },
          { 'num': '46', 'date': '2023-01-17T00:00:00Z' },
          { 'num': '27', 'date': '2023-01-18T00:00:00Z' },
          { 'num': '8', 'date': '2023-01-19T00:00:00Z' },
          { 'num': '19', 'date': '2023-01-20T00:00:00Z' },
          { 'num': '10', 'date': '2023-01-21T00:00:00Z' },
          { 'num': '11', 'date': '2023-01-22T00:00:00Z' },
          { 'num': '22', 'date': '2023-01-23T00:00:00Z' },
          { 'num': '13', 'date': '2023-01-24T00:00:00Z' },
          { 'num': '14', 'date': '2023-01-25T00:00:00Z' },
          { 'num': '16', 'date': '2023-01-26T00:00:00Z' },
          { 'num': '19', 'date': '2023-01-27T00:00:00Z' },
          { 'num': '20', 'date': '2023-01-28T00:00:00Z' },
          { 'num': '27.335291', 'date': '2023-01-29T00:00:00Z' },
          { 'num': '30', 'date': '2023-01-30T00:00:00Z' },
          { 'num': '27.52708', 'date': '2023-01-31T00:00:00Z' },
          { 'num': '42.431682', 'date': '2023-02-01T00:00:00Z' },
          { 'num': '29.000345', 'date': '2023-02-02T00:00:00Z' },
          { 'num': '30.295383', 'date': '2023-02-03T00:00:00Z' },
          { 'num': '20', 'date': '2023-02-04T00:00:00Z' },
          { 'num': '40', 'date': '2023-02-05T00:00:00Z' },
          { 'num': '20', 'date': '2023-02-06T00:00:00Z' },
          { 'num': '10', 'date': '2023-02-07T00:00:00Z' },
          { 'num': '25.947509', 'date': '2023-02-08T00:00:00Z' },
          { 'num': '24.002308', 'date': '2023-02-09T00:00:00Z' },
          { 'num': '10.800104', 'date': '2023-02-10T00:00:00Z' },
          { 'num': '9', 'date': '2023-02-11T00:00:00Z' },
          { 'num': '8', 'date': '2023-02-12T00:00:00Z' },
          { 'num': '7', 'date': '2023-02-13T00:00:00Z' },
          { 'num': '10.871253', 'date': '2023-02-14T00:00:00Z' },
          { 'num': '6.067091', 'date': '2023-02-15T00:00:00Z' },
          { 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' },
          { 'num': '11.452223', 'date': '2023-02-17T00:00:00Z' },
          { 'num': '10', 'date': '2023-02-18T00:00:00Z' },
          { 'num': '3', 'date': '2023-02-19T00:00:00Z' },
          { 'num': '2.257111', 'date': '2023-02-20T00:00:00Z' },
          { 'num': '1', 'date': '2023-02-21T00:00:00Z' }]
      }else if (date=='wek') {
        list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
          { 'num': '8', 'date': '2023-01-19T00:00:00Z' },
          { 'num': '16', 'date': '2023-01-26T00:00:00Z' },
          { 'num': '29.000345', 'date': '2023-02-02T00:00:00Z' },
          { 'num': '24.002308', 'date': '2023-02-09T00:00:00Z' },
          { 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' }]
      }else{
        list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
          { 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' }]
      }
      const result: any = {
        //每一项数据的日期
        categoryData: [],
        //每一项数据的value值
        valueData: []
      }
      if (list) {
        list.forEach(item => {
          result.categoryData.push(item.date.slice(0, 10))
          result.valueData.push(item.num)
        })
      }
      echartDateObj.value = result
      initialize(num, width)
    }

    const volTime = ref({ day: '', month: '', year: '', current: '' })

    const mouthEn = months => {
      return months == 1
        ? 'Jan'
        : months == 2
          ? 'Feb'
          : months == 3
            ? 'Mar'
            : months == 4
              ? 'Apr'
              : months == 5
                ? 'May'
                : months == 6
                  ? 'Jun'
                  : months == 7
                    ? 'Jul'
                    : months == 8
                      ? 'Aug'
                      : months == 9
                        ? 'Sep'
                        : months == 10
                          ? 'Oct'
                          : months == 11
                            ? 'Nov'
                            : 'Dec'
    }

    const initialize = (val, wid) => {
      const chartpillar: any = document.getElementById('echartsBox')
      const myPillar = echarts.init(chartpillar)
      //用来做图上渐变色
      const colorList = [
        '#182025',
        '#181E23',
        '#192832',
        '#1B2B38',
        '#1C2F3E',
        '#1F3444',
        '#1E3545',
        '#213B4F',
        '#254156',
        '#26455A',
        '#294961',
        '#2D4E67',
        '#2E536C',
        '#335772',
        '#365C78',
        '#3B6380',
        '#3F6886',
        '#406987',
        '#45708E',
        '#487393',
        '#4F7B9C',
        '#5580A3',
        '#5886A9',
        '#5F8BAF',
        '#6390B4',
        '#6390B4',
        '#5F8BAF',
        '#5886A9',
        '#5580A3',
        '#4F7B9C',
        '#487393',
        '#45708E',
        '#406987',
        '#3F6886',
        '#3B6380',
        '#365C78',
        '#335772',
        '#2E536C',
        '#2D4E67',
        '#294961',
        '#26455A',
        '#254156',
        '#213B4F',
        '#1E3545',
        '#1F3444',
        '#1C2F3E',
        '#1B2B38',
        '#192832',
        '#181E23',
        '#182025'
      ]

      let optionPillar: any = {
        tooltip: {
          trigger: 'axis',
          //显示框始终固定在图形顶部
          position: function (point, params, dom, rect, size) {
              console.log(point,'point')
              //返回鼠标x、y(横向、纵向)两个点的位置
            return [point[0] - 50, '10%']
          },
          backgroundColor: '#3B6380',
          borderColor: 'transparent',
          extraCssText: 'height:24px;',
          formatter: function (params) {
            let months = params[0].axisValue.slice(5, 7)
            let value = mouthEn(months)
            const day = params[0].axisValue.slice(8, 10)
            const month = value
            const year = params[0].axisValue.slice(0, 4)
            volTime.value = {
              day: day,
              month: month,
              year: year,
              current: ''
            }
            console.log(params[0].value, 'params[0].value')

            leftShowNum.value = params[0].value
            return '&nbsp;&nbsp;&nbsp;' 
            + day + '&nbsp;' + month + '&nbsp;' + year + '&nbsp;&nbsp;&nbsp;'
          },
          textStyle: {
            color: '#909DB4',
            innerHeight: '24',
            lineHeight: '24' // 行高
          },
          padding: 0,
          axisPointer: {
            type: 'line',
            lineStyle: {
              width: 4,
              type: 'solid',
              color: 'blue'
            }
          }
        },
        xAxis: {
          max: echartDateObj.value.categoryData.length > 40 
          ? 40 : echartDateObj.value.categoryData.length - 1,
          type: 'category',
          axisTick: {
            show: false
          },
          axisLine: {
            show: false
          },
          splitLine: {
            show: false
          },
          splitArea: {
            show: false
          },
          data: echartDateObj.value.categoryData,
          axisLabel: {
            formatter: (val, index) => {
              let showdata: any
              let months = val.slice(5, 7)
              let mValue = mouthEn(months)
              if (echartVal.value == 'M') {
                showdata = mValue
              } else {
                showdata = val.slice(8, 10)
              }
              return `${showdata}`
            }
          }
        },
        yAxis: {
          show: false,
          max: function (value) {
            return value.max
          },
          splitArea: { show: false }
        },
        dataZoom: [
          {
            type: 'inside',
            start: 0,
            end: val,
            zoomLock: true
          }
        ],
        series: [
          {
            data: echartDateObj.value.valueData,
            type: 'bar',
            itemStyle: {
              normal: {
                barBorderRadius: 1,
                color: params => {
                  return colorList[params.dataIndex]
                }
              }
            },
            barWidth: wid //柱图宽度
          }
        ],
        grid: {
          left: 0,
          top: 0,
          // bottom: 0,
          right: 24
        }
      }
      if (document.body.clientWidth < 750) {
        optionPillar.grid = {
          // bottom: 20,
          left: 4,
          top: 0,
          bottom: 20,
          right: 24
        }
      }
      optionPillar.tooltip.backgroundColor = '#3B6380'
      //  对实例对象进行设置配置
      optionPillar && myPillar.setOption(optionPillar)
      myPillar.on('globalout', params => {
        volTime.value = { day: '', month: '', year: '', current: '' }
        leftShowNum.value = ''
      })
    }

    return {
      changeEchart,
      echartVal,
      volTime,
      leftShowNum
    }
  }
})
</script>
<style lang="less" scoped>
@import '../assets/css/base.less';

.echarts-container {
  width:920px;
  padding: 0 2px;

  .echarts-content-box {
    margin: 200px 0;
    padding-top: 16px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    position: relative;
    .echarts-tab {
      padding-right: 20px;
      display: flex;
      align-items: center;
      z-index: 99999;
      margin-bottom: 8px;
      p {
        color: @textActive;
        margin-bottom: 0 !important;
        margin-right: 10px;
      }
      > div {
        cursor: pointer;
        width: 24px;
        height: 24px;
        background: @cardEmphasize;
        border: 1px solid transparent;
        text-align: center;
        line-height: 24px;
        color: @textDefault;
        &:hover {
          color: @textActive;
        }
      }
      .title-active {
        color: @textActive;
        border: 1px solid @borderDefault;
        background: @buttonDetailDefault;
      }
    }
    .echarts-content {
      width: 100%;
      height: 300px;
      padding: 20px 0px 10px 0px;
      display: flex;
      justify-content: space-between;

      .left {
        position: absolute;
        top: 16px;
        left: 0;
        span {
          font-size: 14px;
          color: @textDefaultStats;
        }

        p {
          margin-bottom: 0 !important;
          color: blue;
          font-size: 20px;
          font-weight: 800;
        }
      }

      .right {
        margin-bottom: 100px ;
        width: 100%;
        height: 316px;
        padding: 0px;
        z-index: 9999;
      }
    }
  }
}
</style>

代码贴上了,如果效果类似,可直接粘贴到项目里面调,现在拆开看下属性

代码梳理--api讲解


代码有点多,都贴进去了,看起来感觉是一团乱麻,但是拆开来看就比较好理解了。

页面上的代码使用的四个方法

首先页面上我们用到了四个方法changeEchart(),getEchartDate(),mouthEn(),initialize()

1.changeEchart方法

  • 传了1个val参数,用来根据日周月来重新获取图表数据的,点击日或者周或者月,我们就可以重新调取接口,获取我们想要的日或者周或者月的数据

2.getEchartDate方法

  • 传了5个参数,里面大多是获取接口数据时用到的,但是案例中没有接口,我直接把数据写死了
    • val title date这三个是接口需要的,不多说了
    • num width这两个是初始化图表用的,num用来表示数据窗口范围的结束百分比,width是表示柱状图一根多宽
  • 有接口时我们可以将获取的数据处理成我们想要的样子放到echartDateObj对象中,一般回来的都是数组的形式,数组里面是一个一个的对象,对象里面是日期和value值,但是我们需要把日期和value值分开重新放到两个数组里面用,所以上面把日期放到了echartDateObj对象的categoryData中,把value值放到了valueDate中

3.mouthEn方法

  • 主要是用来处理数据的,把月份转为英文的月份,需求需要

4.initialize方法

  • initialize我们就比较熟悉了,初始化图表。具体说下api

echarts -- api

一.tooltip:鼠标移到图表上面显示x,y轴具体信息

tooltip.jpeg

1.trigger:
  • tooltip可以显示x,y轴的相关数据的
  • 默认值 item ,可选值 itemaxis
  • 当trigger为item时只会显示该点的数据,为axis时显示该列下所有坐标轴所对应的数据。
2.position:
  • tooltip的位置设置,五个参数,tooltip默认是根据鼠标的移动而移动,视觉焦点始终是与鼠标保持一致,但我们可以根据需求对tooltip的位置做特殊处理,让其固定在图形顶部。详细设置可以参考www.shulanxt.com/visualizati… ,实在是有点多,然后找了一篇相对详细的博客,可以看下(如侵权可删除)
    • point:  鼠标位置,是一个数组,如 [20, 50]
    • params:  Object|Array. 是需要的数据集
    • dom:  tooltip 的 dom 对象。 rect:一个对象,只有鼠标在图形上时有效,是一个用 x, y, width, height 四个属性表达的图形包围盒。
    • size:  一个对象,包括 dom 的尺寸和 echarts 容器的当前尺寸,例如:{contentSize: [width, height], viewSize: [width, height]}
    • size中有两个属性:  viewSize为外层div的大小,contentSize为tooltip提示框的大小
3.backgroundColor:
  • tooltip背景颜色,效果等同optionPillar.tooltip.backgroundColor = '#色值'
4.borderColor:
  • tooltip边框颜色,效果等同optionPillar.tooltip.borderColor = '#色值'
5.extraCssText:
  • tooltip---设置css,比如案例中extraCssText: 'height:64px;'
6.formatter:
  • 打印了下params参数,可以参考,有比较全的x轴和y轴的各种信息,或者到时候你们打印自己项目里的,可以根据需求和params来组织tooltip echart-params.jpeg
7.textStyle:
  • tooltip---文本的css设置,比如案例中颜色行高等
8.axisPointer:
  • 是坐标轴指示器,默认是 x 轴
  • 其实也可以改变为 y 轴,如下:tooltip.axisPointer.axis = 'y',
    xAxis.axisPointer.lineStyle.color = "#f00";
    yAxis.axisPointer.lineStyle.color = "#0f0";
    此时会发现十字相交线的竖线是红色,横线是绿色
    • line:  鼠标移上去,所在值出现一条指示线,默认针对 x 轴,即竖线
    • shadow:  鼠标移上去,所在值出现一条指示阴影(类似于一个小矩形),默认针对  x 轴
    • cross:  鼠标移上去,所在值出现纵横交叉的指示线
    • none:  鼠标移上去,无指示

二.xAxis: x坐标轴相关属性

更多详细配置可查看juejin.cn/post/709933… ,这个是掘金上其他博主总结的,我看着很详细,有需要可以参考(如侵权可删除)

xaxis.jpeg

1. max:  x轴最多显示数据条数
2. type:  坐标轴类型
  • value:  数值轴,适用于连续数据
  • category:  类目轴,适用于离散的类目数据,为该类型时必须通过 data 设置类目数据
  • time:  时间轴,适用于连续的时序数据,与数值轴相比时间轴带有时间的格式化,在刻度计算上也有所不同,例如会根据跨度的范围来决定使用月,星期,日还是小时范围的刻度
  • log:  对数轴,适用于对数数据
3.axisTick:  坐标轴刻度相关配置
  • show:  Boolean,默认值true,是否显示坐标轴刻度
4.axisLine:  坐标轴轴线相关配置
  • show: Boolean,默认true, 是否显示坐标轴轴线
5.splitLine:  坐标轴在 grid 区域中的分隔线
  • show: Boolean,是否显示分隔线。默认数值轴显示,类目轴不显示
6.splitArea:  坐标轴在 grid 区域中的分隔区域,默认不显示
  • show: Boolean ,默认true, 是否显示分隔区域
7.date:  Array 类目数据,x轴数据数组,也就是我们上述中的日期数组
  • Array 类目数据,在类目轴(type: 'category')中有效
  • 如果没有设置 type,但是设置了 axis.data,则认为 type 是 'category'
  • 如果设置了 type 是 'category',但没有设置 axis.data,则 axis.data 的内容会自动从 series.data 中获取
  • 注意,axis.data 指明的是 'category' 轴的取值范围
  • 如果不指定而是从 series.data 中获取,那么只能获取到 series.data 中出现的值
  • 如果series.data 为空时,就什么也获取不到
8.axisLabel:  坐标轴刻度标签的相关设置 (刻度对应的文本)
  • formatter: String/Function 刻度标签的内容格式器 ,x轴刻度上显示的文案
    • 支持模板字符串和回调函数两种形式
    • 使用模板字符串,模板变量为刻度默认标签 {value}
    • 使用函数模板,函数参数分别为刻度数值(类目),刻度的索引

三.yAxis: y坐标轴相关属性

image.png

1. show:  是否显示y轴刻度
2. max:  y轴刻度的最大值设置

四.dataZoom: 用于区域缩放

image.png

1. type:
  • 两个值,第一个就是slider,有单独的滑动条,用户在滑动条上进行缩放或漫游
  • 另一个值是inside,内置于坐标系中,使用户可以在坐标系上通过鼠标拖拽、鼠标滚轮、手指滑动(触屏上)来缩放或漫游坐标系。
2. start: 窗口初始显示数据的范围
3. end: 窗口范围结束的百分比
4. zoomLock: 是否锁定视图,或者说限制窗口的大小

五.series: 系列图标配置,图表类型

image.png

1. date: 图表数据,这里的数据是y轴数据,所以我们写的对应日期的value值
2. type: 图表类型
  • bar:柱状/条形图
  • line:折线/面积图
  • pie:饼图
  • scatter:散点(气泡)图
  • effectScatter:带有涟漪特效动画的散点(气泡)
  • radar:雷达图
  • tree:树型图
  • treemap:树型图
  • sunburst:旭日图
  • boxplot:箱形图
  • candlestick:K线图
  • heatmap:热力图
  • map:地图
  • parallel:平行坐标系的系列
  • lines:线图
  • graph:关系图
  • sankey:桑基图
  • funnel:漏斗图
  • gauge:仪表盘
  • pictorialBar:象形柱图
  • themeRiver:主题河流
  • custom:自定义系列
3. itemStyle: 单个数据项样式

六.grid: 图标离容器的距离

image.png

1. show: Boolean,是否显示直角坐标系网格
2. left: 图表离容器左侧的距离
3. top: 图表离容器顶部的距离
4. right: 图表离容器右侧的距离
5. bottom: 图表离容器底部的距离
6. backgroundColor: 网格背景色,rgba或#000
7. borderColor: 网格的边框颜色,rgba或#000
8. borderWidth: 网格的边框线宽,number

总结

echats的api真的超级超级多,我们的需求大多时候它都是可以满足的,但是这个api是真的不好找,本文也就仅仅是写了一部分用到的api,补充的不多,想找完整的还是得按照单个api查详细的说明,但是如果有ui跟这个很类似的那就比较好了,直接拿去用~记得想看哪个属性的话用目录找,文章太长了,不好查。