«

Vue+Echarts怎么实现分时图和交易量图绘制

时间:2024-8-1 08:54     作者:韩俊     分类: Javascript


这篇文章主要介绍“Vue+Echarts怎么实现分时图和交易量图绘制”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue+Echarts怎么实现分时图和交易量图绘制”文章能帮助大家解决问题。

    分时图

    1 vue引入Echarts

    2 分时图介绍

    分时图本质上也是一个折线图,横坐标为一天交易的每一分钟,纵坐标为股市的实时单价。除了实现这两个基本的功能以外,还需要带上每分钟交易量图,当鼠标放在图上时,要展示当前时间对应的相关数据;如下图所示:

    我们本期要实现的功能为:分时折线图、分时成交量图,鼠标指示展示详细数据,对应成交量颜色划分;其余的一些细节的功能(图切换,细节颜色以及样式处理)我们以后再做介绍。

    3 分时折线图配置

    分时折线图本质上是折线图,我们通过设置图类型为折线即可,重点是对数据的处理,我们的数据源格式是json对象数组数据,每一分钟数据如下所示:

    {"time":"1678411800","price":"3255.51","ratio":"-0.63%","increase":"-20.58","volume":"2925368","avgPrice":"3261.35","amount":"29.00u4ebf","timeKey":"0930","datetime":"03-10 09:30","oriAmount":"2900320446","show":"1"},

    首先我们需要对数据进行处理,才能应用于Echarts之中;我们分时折线图配置项代码代码如下所示:

     // 横坐标数据配置
            xAxis: [
              {
                type: "category",
                data: this.xData,
                boundaryGap: false,
                axisLine: { onZero: false },
                splitLine: { show: false },
                min: "dataMin",
                max: "dataMax"
              },
            ]
    // 纵坐标配置
            yAxis: [
              {
                scale: true,
                splitArea: {
                  show: true
                }
              },
            ]
    //图形数据配置:
            series: [
              {
                type: "line",
                data: this.hourData,
                symbol: "none", //无标记图案
                lineStyle: {
                  width: 1
                }
              },
            ]

    其中,this.xData是我们vue页面中的经过处理的横坐标数据,this.hourData是我们页面中经过处理的每小时数据。

    注意:series中symbol属性要设置为none,这样的到的折线图上将会不出线标记图案。

    数据处理代码如下:

        // 横坐标数据处理
        initxData() {
          for (let i = 0; i < this.klineData.length; i++) {
            this.xData[i] = this.klineData[i].datetime;
          }
        },
            // 数据计算以及拆分,将json数据转为数组数据
        splitData(jsonData) {
          const hourData = [];
          for (let i = 0; i < jsonData.length; i++) {
            hourData.push([
              i,
              jsonData[i].price,
              jsonData[i].increase,
              jsonData[i].volume,
              jsonData[i].ratio,
              jsonData[i].amount,
              jsonData[i].datetime
            ]);
          }
          return hourData;
        }

    其中, this.klineData是我们页面引入的json数据。

    到此我们可以来看一下分时折线图的效果:

    可以看到得到的折线图就是为我们的分时折线图。

    4 组合交易量图

    交易量图为2.2图中底部的红绿交间的柱状图,交易量图本质是一个柱状图,我们可以看到有两个特点:

    1.横坐标与分时折线图公用,且柱状图在交易图下方;

    2.当前为涨时,柱子为红色,当前为跌时,柱子为绿色;

    对于特点1,在我们之前介绍的图中,都是公用坐标系的图,这里新知识点就是不公用坐标系,但是公用横坐标数据应该怎么处理;就是在xAxis、yAxis和series中设置两个对象出来,代表两个不同的坐标西,然后将两个坐标系的横坐标进行对齐即可;

    代码如下:

    // 横坐标数据
            xAxis: [
              // 折线图
              {
                type: "category",
                data: this.xData,
                boundaryGap: false,
                axisLine: { onZero: false },
                splitLine: { show: false },
                min: "dataMin",
                max: "dataMax"
              },
              // 柱状图
              {
                type: "category",
                gridIndex: 1, //x 轴所在的 grid 的索引,默认位于第一个 grid。
                data: this.xData,
                boundaryGap: false,
                axisLine: { onZero: false },
                axisTick: { show: false },
                splitLine: { show: false },
                axisLabel: { show: false },
                min: "dataMin",
                max: "dataMax"
              }
            ],
            // 纵坐标配置
            yAxis: [
              {
                scale: true,
                splitArea: {
                  show: true
                }
              },
              {
                scale: true,
                gridIndex: 1, // y 轴所在的 grid 的索引,默认位于第一个 grid
                splitNumber: 2,
                axisLabel: { show: false },
                axisLine: { show: false },
                axisTick: { show: false },
                splitLine: { show: false }
              }
            ],
             series: [
              {
                type: "line",
                data: this.hourData,
                symbol: "none", //无标记图案
                lineStyle: {
                  width: 1
                }
              },
              {
                name: "Volume",
                type: "bar",
                xAxisIndex: 1,
                yAxisIndex: 1,
                data: this.culomnValue
              }
            ]

    对于特点2,控制每个柱状图颜色不同,我们需要用到visualMap.pieces属性;官网上对该属性的说明是:自定义『分段式视觉映射组件(visualMapPiecewise)』的每一段的范围,以及每一段的文字,以及每一段的特别的样式。

    我们直接上代码以及讲解,来看这个属性怎么使用,代码如下:

             visualMap: {
              type: "piecewise",
              show: false, //不展示map,只应用对应颜色划分逻辑
              seriesIndex: 1, //指定取哪个系列的数据
              dimension: 2,
              // 定义每一段的颜色
              pieces: [
                {
                  value: -1,
                  color: this.downColor
                },
                {
                  value: 1,
                  color: this.upcolor
                }
              ]
            },

    这段代码的解释是:当series的data数据里面有value==-1的值时,使用color为this.downColor,value==1时,使用color为this.upcolor.

    此时,我们还需要对颜色数据进行处理一下,将k线图对应时间段的增长和下跌展示在数组里面,成交量数据处理代码如下:

        // 初始化交易数据和交易柱状图颜色参数
        initCulomnColor() {
          this.culomnColor[0] = this.klineData[0].increase > 0 ? 1 : -1;
          this.culomnValue[0] = [0, this.klineData[0].volume, -1];
          for (let i = 1; i < this.klineData.length; i++) {
            this.culomnColor[i] =
              this.klineData[i].price > this.klineData[i - 1].price ? 1 : -1;
            this.culomnValue[i] = [
              i,
              this.klineData[i].volume,
              this.culomnColor[i]
            ];
          }
        },

    到这里我们成交量柱状图即可渲染出来了,下一步就是将折线图和柱状图位置进行调整,给两个图分配合适的区域,代码如下:

     // 图像位置配置
            grid: [
              {
                left: "10%",
                right: "10%",
                height: "50%"
              },
              {
                left: "10%",
                right: "10%",
                top: "65%",
                height: "18%"
              }
            ],

    grid配置两个对象分别代表折线图和柱状图位置;

    融合之后我们看到的效果图如下:

    5 鼠标指示数据设置

    k线图的要求是当鼠标指示在图的某个位置时,需要将这个时间段的详细数据展示出来;在此我们需要要利用到tooltip属性,但这个属性默认之后展示当前横坐标和纵坐标的值,吐过需要对展示的数据进行配置的话,我们还需要借助tooltip.formatter属性来返回我们想要的展示的数据,该属性可拓展范围非常广,本次不展开介绍,只介绍在k线图中的基本使用。代码如下:

    tooltip: {
              trigger: "axis",
              axisPointer: {
                type: "cross" //十字准星指示器
              },
              borderWidth: 1,
              borderColor: "#ccc",
              padding: 10,
              textStyle: {
                color: "#000"
              },
              formatter: function(param) {
                param = param[0];
                return [
                  "时间: " + param.data[6] + '<hr size=1 >',
                  "价格: " + param.data[1] + "<br/>",
                  "涨跌额: " + param.data[2] + "<br/>",
                  "成交量: " + param.data[3] + "<br/>",
                  "涨跌幅: " + param.data[4] + "<br/>"
                ].join("");
              }
            },

    我们将:时间、价格、涨跌额、成交量、涨跌幅五个属性展示在页面上,样式从简。得到的效果如下:

    至此基本完成了分时折线图和交易量图的绘制;

    6 项目完整代码

    vue项目完整代码如下:

    <template>
      <div class="echart" id="mychart" ></div>
    </template>
    
    <script>
    import * as echarts from "echarts";
    import SZHourData from "./data/hourData.TS";
    
    export default {
      data() {
        return {
          upcolor: "#FF0000", //增长颜色
          upBorderColor: "#8A0000",
          downColor: "#008000", // 下跌颜色
          downBorderColor: "#008F28",
          klineData: [], //k线图数据
          hourData: [], //charts表格小时数据
          xData: [],
          culomnColor: [], //颜色
          culomnValue: []
        };
      },
      mounted() {
        // 数据初始化
        this.initData();
        // 图标初始化
        this.initEcharts();
      },
      methods: {
        initData() {
          this.klineData = SZHourData.priceinfo;
          this.hourData = this.splitData(this.klineData);
          this.initxData();
        },
        initEcharts() {
          const option = {
            title: {
              text: "上证指数",
              left: 0
            },
            tooltip: {
              trigger: "axis",
              axisPointer: {
                type: "cross" //十字准星指示器
              },
              borderWidth: 1,
              borderColor: "#ccc",
              padding: 10,
              textStyle: {
                color: "#000"
              },
              formatter: function(param) {
                param = param[0];
                return [
                  "时间: " + param.data[6] + '<hr size=1 >',
                  "价格: " + param.data[1] + "<br/>",
                  "涨跌额: " + param.data[2] + "<br/>",
                  "成交量: " + param.data[3] + "<br/>",
                  "涨跌幅: " + param.data[4] + "<br/>"
                ].join("");
              }
            },
    
            visualMap: {
              type: "piecewise",
              show: false, //不展示map,只应用对应颜色划分逻辑
              seriesIndex: 1, //指定取哪个系列的数据
              dimension: 2,
              // 定义每一段的颜色
              pieces: [
                {
                  value: -1,
                  color: this.downColor
                },
                {
                  value: 1,
                  color: this.upcolor
                }
              ]
            },
            // 图像位置配置
            grid: [
              {
                left: "10%",
                right: "10%",
                height: "50%"
              },
              {
                left: "10%",
                right: "10%",
                top: "65%",
                height: "18%"
              }
            ],
            // 横坐标数据
            xAxis: [
              // 折线图
              {
                type: "category",
                data: this.xData,
                boundaryGap: false,
                axisLine: { onZero: false },
                splitLine: { show: false },
                min: "dataMin",
                max: "dataMax"
              },
              // 柱状图
              {
                type: "category",
                gridIndex: 1, //x 轴所在的 grid 的索引,默认位于第一个 grid。
                data: this.xData,
                boundaryGap: false,
                axisLine: { onZero: false },
                axisTick: { show: false },
                splitLine: { show: false },
                axisLabel: { show: false },
                min: "dataMin",
                max: "dataMax"
              }
            ],
            // 纵坐标配置
            yAxis: [
              {
                scale: true,
                splitArea: {
                  show: true
                }
              },
              {
                scale: true,
                gridIndex: 1, // y 轴所在的 grid 的索引,默认位于第一个 grid
                splitNumber: 2,
                axisLabel: { show: false },
                axisLine: { show: false },
                axisTick: { show: false },
                splitLine: { show: false }
              }
            ],
            dataZoom: [
              {
                type: "inside",
                xAxisIndex: [0, 1],
                start: 50, //展示的数据范围,默认为50%-100%
                end: 100
              },
              {
                show: true,
                xAxisIndex: [0, 1],
                type: "slider",
                top: "90%",
                start: 50, //展示的数据范围,默认为50%-100%
                end: 100
              }
            ],
            series: [
              {
                type: "line",
                data: this.hourData,
                symbol: "none", //无标记图案
                lineStyle: {
                  width: 1
                }
              },
              {
                name: "Volume",
                type: "bar",
                xAxisIndex: 1,
                yAxisIndex: 1,
                data: this.culomnValue
              }
            ]
          };
          const myChart = echarts.init(document.getElementById("mychart"));
          myChart.setOption(option);
          //随着屏幕大小调节图表
          window.addEventListener("resize", () => {
            myChart.resize();
          });
        },
        // 横坐标数据处理
        initxData() {
          for (let i = 0; i < this.klineData.length; i++) {
            this.xData[i] = this.klineData[i].datetime;
          }
          this.initCulomnColor();
        },
        // 初始化交易数据和交易柱状图颜色参数
        initCulomnColor() {
          this.culomnColor[0] = this.klineData[0].increase > 0 ? 1 : -1;
          this.culomnValue[0] = [0, this.klineData[0].volume, -1];
          for (let i = 1; i < this.klineData.length; i++) {
            this.culomnColor[i] =
              this.klineData[i].price > this.klineData[i - 1].price ? 1 : -1;
            this.culomnValue[i] = [
              i,
              this.klineData[i].volume,
              this.culomnColor[i]
            ];
          }
        },
        // 数据计算以及拆分,将json数据转为数组数据
        splitData(jsonData) {
          const hourData = [];
          for (let i = 0; i < jsonData.length; i++) {
            hourData.push([
              i,
              jsonData[i].price,
              jsonData[i].increase,
              jsonData[i].volume,
              jsonData[i].ratio,
              jsonData[i].amount,
              jsonData[i].datetime
            ]);
          }
          return hourData;
        }
      }
    };
    </script>

    标签: javascript vue

    热门推荐