echarts绘制分时图(2)-- 配置echarts

简单介绍

工作中需要绘制公司的分时和日k,但是接口要自己找。于是我就使用了腾讯的接口调分时和日k数据,新浪的接口调股票基本信息。如股票名字、今日开盘价、昨日收盘价、当前价格等等。均价线目前还没有。
参考资料:
https://blog.csdn.net/m0_37992075/article/details/84288021
https://blog.csdn.net/luanpeng825485697/article/details/78442062?locationNum=5&fps=1

配置echarts遇到的问题

配置参数过程中,遇到的最大问题就是处理分时图的y轴坐标。如图,分时线涨幅计算是以前天收盘价为基准。为了能让前一天收盘价显示出来,折腾了我好久。
在这里插入图片描述
解决思路:
y轴上的数据是一个等差数列,要想让前一天收盘价展示出来,需要数列中含有它。
y轴坐标值主要与 max(y轴最大值),min(最小值),interval(分割间隔)有关。
所以我们根据已经有的数据赋值三个变量即可。
**已知数据:**前一天收盘价(baseNumber)
计算max、min:
通过Math.max.apply(),Math.min.apply()方法拿到已有数据中的最大最小成交价并计算出涨幅,对比最大和最小涨幅比取较大的值( handle_num() ),就可以计算出y轴目前需要的最高(max)和最低(min)范围。

var _minVal = Number(baseNumber-baseNumberhandle_num()).toFixed(2);
var _maxVal = (Number(baseNumber)+baseNumber
handle_num()).toFixed(2);

计算涨幅比后去求得的范围才是我们需要的,不直接取数组中最大最小值的原因是,最低价不一定小于baseNumber,如果今日开盘价全部高于baseNumber,图表绘制出来是错误的。用最大涨幅比计算的涵盖所有数据,较为可行。而且这样计算出来的,涨跌幅绝对值也一致。
计算interval:
interval 其实就是 折线图data的一个公差,套用an=a1+(n-1)d公式便可以计算出来。

由于y轴赋值min后,起点就会为min值,求公差时可以以 baseNumber 为 an,min 为a1,n为5。

这里n作用和splitNumber类似,但也不同,n的大小会影响y轴坐标密集程度,具体可根据数据大小调整。

yAxis 配置:
因为是双y轴,所以第二个配置中,min、max、interval 需要设置相同数值才能在同一水平线。
ps: 此图表的 双y轴,其实是绘制了两条折线,通过position偏移一条,并将折线宽度设置为0,因此两条y轴数值完全一样便于配置。涨幅比是通过axisLabel>formatter更改坐标轴的。

yAxis: [ //y轴
      {
        type: 'value',
        min: _minVal,
        max: _maxVal,
        interval: _interval,
        gridIndex: 0,
        scale: true,
        axisTick: { // 分割线 短
          show: false
        },
        axisLine: {
          lineStyle: {
            color: borderColor,
          }
        },
        axisPointer: {
          show: true,
          label: {
            formatter: function (params) { 
              return (params.value).toFixed(2);
            }
          }
        },
        axisLabel: {
          color:'#333',
          formatter: format_y,
          rich: {
            red: {
                color: 'red',
                lineHeight: 10
            },
            green: {
                color: 'green',
                lineHeight: 10
            }
          }
        },
        z: 4,
        splitLine: { //分割线设置
          show: true,
          lineStyle: {
            type: 'dashed'
          }
        },
      },{
        scale: true,
        gridIndex: 1,
        min: _minVal,
        max: _maxVal,
        interval: _interval,
        position: 'right',
        z: 4,
        axisTick: {
          show: false
        },
        axisLine: {
          lineStyle: {
            color: borderColor,
          }
        },
        axisLabel: { //label文字设置
          color: function (val) {
            val = Number(val).toFixed(2)
            if (val == baseNumber) {
              return '#333'
            }
            return val > baseNumber ? upColor : downColor;
          },
          formatter: function (val) {
            var resul = ratioCalculate(val, baseNumber);
            return Number(resul).toFixed(2) + '%'
          }
        },
        splitLine: { //分割线设置
          show: false,
          lineStyle: {
            color: '#181a23'
          }
        },
        axisPointer: {
          show: true,
          label: {
            formatter: function (params) { //计算右边Y轴对应的当前价的涨幅比例
              return ratioCalculate(params.value, baseNumber) + '%';
            }
          }
        }
      },{// 成交量的y轴配置
      //...已省略
      }
	]

echarts绘制分时图(1)-- 接收及处理股票接口数据

demo放在这里了 ,欢迎指正和交流。

--------------2024.4.8更新----------
因为很久很久之后又做了个画图的功能,发现之前计算的有问题,本来不想维护这个文章的,但是还偶尔有朋友点赞,让我很不好意思。
更新一下计算的逻辑。好像主要是昨日收盘价和今日最高最低价的计算要区分下,影响了分割值。时间太久了,我翻了半天才找出来当年的代码。
下面的代码和demo里的不一样哈,仅供参考帮助梳理。
如果帮助到你了,很荣幸~ 以后这个就不更新了,主要下面的项目也是很久之前的了,我记不太清了。敲代码越来越累,脑子不好使,我想去烤串卖蛋糕,,,,

function splitTimeSaringData(mapRawData) { // map存储的值
  let categoryData = [];
  let volumes = []; // 成交量 [index, ]
  let price = []; // 成交价
  let closingPrice = 0;
  let chgValue = [];
  let minVal = 0;
  let maxVal = 0;
  const entries = mapRawData.entries();
  for (let i = 0; i < mapRawData.size; i++) {
    const entry = entries.next().value;
    const val = entry[1];
    if (!closingPrice) {
      closingPrice = Number(val.preClosePrice);
    }
    if (!Number.isNaN(parseInt(val["tradePrice"]) - 0) && val["tradePrice"]) {
      const _val = Number(val["tradePrice"]);
      if (!minVal) {
        minVal = _val;
      } else {
        minVal = _val < minVal ? _val : minVal;
      }
      if (!maxVal) {
        maxVal = Number(val["tradePrice"]);
      } else {
        maxVal = _val > maxVal ? _val : maxVal;
      }
    }
    // categoryData.push(entry[0]);
    price.push(val["tradePrice"]);

    chgValue.push(val["chgValue"]);
    // [x, 分钟成交量, 分钟涨跌: false 跌、true 涨、 其他 不变]
    volumes.push([
      val["timestamp"],
      val["minTradeVolume"],
      val["minChgInc"] ? 1 : -1,
    ]);
  }
  return {
    // categoryData: categoryData,
    price: price,
    volumes: volumes,
    closingPrice: closingPrice,
    chgValue: chgValue,
    minVal: minVal,
    maxVal: maxVal,
  };
}
// 分时图 配置项-赋值
export const getTimeSharingChartData = (mapData) => {
  const data = splitTimeSaringData(mapData);
  const closingPrice = data.closingPrice; // 昨日收盘价
  let minVal = data.minVal; // Math.min(...data.price);
  let maxVal = data.maxVal; // Math.max(...data.price);
  let interval;
  if (closingPrice > maxVal) {
    interval = (closingPrice - minVal) / 2;
  } else {
    const absMaxDiff = Math.abs(closingPrice - maxVal);
    const absMinDiff = Math.abs(closingPrice - minVal);
    const diff = absMaxDiff > absMinDiff ? absMaxDiff : absMinDiff;
    interval = diff / 2 + 5; // 增加20的空间
  }
  minVal = (closingPrice - interval * 2).toFixed(2);
  maxVal = (closingPrice + interval * 2).toFixed(2);
  let _per = (((maxVal - closingPrice) / closingPrice / 2) * 100).toFixed(2);
  return {
    title: {
      text: "分时图",
      subtext: closingPrice, // 昨日收盘价
      show: false,
    },
    xAxis: [
      {
        type: "category",
        // data.categoryData
        data: timeSharingXAxis().timeSharingXAxisArray,
        boundaryGap: true,
        axisLine: { onZero: false, show: false },
        axisLabel: { show: false },
        axisTick: {show: false},
        splitLine: {
          show: true,
          interval: 80,
          lineStyle: {
            color: '#f0f0f0'
          }
        },
        axisLine: {
          show: true,
          lineStyle: {
            color: '#f0f0f0'
          }
        },
        axisPointer: {
          label: {
            show: true,
            margin: -10
          },
        },
      },
      {
        type: "category",
        gridIndex: 1,
        data: timeSharingXAxis().timeSharingXAxisArray,
        boundaryGap: true,
        splitLine: { show: false },
        axisTick: {show: false},
        axisLine: { show: false },
        axisPointer: {
          label: {
            show: false,
          },
        },
        axisLabel: {
          show: true,
          fontSize: 10,
          width: 100,
          showMinLabel: true,
          showMaxLabel: true,
          margin: 5,
          interval: 119,
          color: '#333333',
          formatter: (value) => {
            if (value === "09:30") {
              return "{x0930|" + value + "}";
            } else if (value === "15:00") {
              return "{x1500|" + value + "}";
            } else {
              return "{value|" + value + "}";
            }
          },
          rich: {
            x0930: {
              align: "right",
              fontSize: 10,
              padding: [0, 20, 0, 0],
            },
            x1500: {
              align: "left",
              fontSize: 10,
              padding: [0, 0, 0, 20],
            },
            value: {
              fontSize: 10,
            },
          },
        },
        min: 0,
        max: 240,
      }
    ],
    yAxis: [
      {
        gridIndex: 0,
        onZeroAxisIndex: false,
        boundaryGap: true,
        type: "value",
        min: Number(minVal),
        max: Number(maxVal),
        interval: interval,
        fontSize: 10,
        axisLine: {
          show: true,
          lineStyle: {
            color: '#f0f0f0'
          }
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#f0f0f0'
          }
        },
        axisPointer: {
          label: {
            show: true,
          }
        },
        axisLabel: {
          inside: true,
          verticalAlign: "bottom",
          fontSize: 10,
          color: function (val) {
            val = Number(val).toFixed(2);
            if (val == closingPrice) {
              return "#333";
            }
            return val > closingPrice ? upColor : downColor;
          },
          formatter: function (value) {
            return value.toFixed(2);
          },
        }
      },
      {
        gridIndex: 0,
        position: "right",
        alignTicks: true,
        boundaryGap: true,
        type: "value",
        onZeroAxisIndex: false,
        max: Number(_per) * 2,
        min: Number(-_per) * 2,
        interval: Number(_per),
        splitLine: { show: false },
        axisLabel: {
          inside: true,
          formatter: "{value}%",
          fontSize: 10,
          verticalAlign: "bottom",
          color: function (val) {
            val = Number(val).toFixed(2);
            if (val == 0) {
              return "#333";
            }
            return val > 0 ? upColor : downColor;
          },
        },
        axisPointer: {
          label: {
            show: true,
            formatter: "{value}%",
          },
        },
      },
      {
        gridIndex: 1,
        scale: true,
        splitNumber: 3,
        onZeroAxisIndex: false,
        axisLabel: { show: false },
        axisLine: { show: false },
        axisTick: { show: false },
        splitLine: {
          show: false,
          lineStyle: {
            color: '#f0f0f0'
          }
        },
        boundaryGap: true,
      },
    ],
    series: [
      {
        name: "index",
        type: "line",
        connectNulls: true,
        lineStyle: {
          width: 1,
        },
        data: data.price,
        showSymbol: false,
        emphasis: {
          itemStyle: {
            color: '#617cd2',
            borderColor: '#a3b9ff'
          }
        },
        z: 100
      },
      {
        name: "per",
        type: "line",
        lineStyle: {
          width: 0,
        },
        symbol: "none",
        xAxisIndex: 0,
        yAxisIndex: 1,
        data: data.chgValue,
      },
      {
        name: "Volume",
        type: "bar",
        barMaxWidth: 10,
        xAxisIndex: 1,
        yAxisIndex: 2,
        data: data.volumes,
      },
    ]
  };
};
  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值