仅在新数据点上使用绘图线和自定义标记来进行自定义反应

问题描述 投票:0回答:1

我正在使用 highcharts 和 highcharts-react-official 来创建 eth 实时价格图表。我还向用户展示了我从父组件中获取的当前回合详细信息,它像这样渲染(附图)还添加了 startTime 和 endTime 的绘图线。如您所见,情节文本已被截断。
enter image description here

这就是我想要复制的包含所有详细信息和功能的确切图表。

enter image description here

这是我的代码

startedRoundData
import React, { useEffect, useState } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import moment from "moment";

const Chart = ({ data, startedRoundData }) => {
  const [chartOptions, setChartOptions] = useState({});

  useEffect(() => {
    const pricesData = data?.prices || [];
    const chartData = pricesData
      .slice(0, -1)
      .map((item) => [item.timestamp * 1000, parseFloat(item.price)]);

    const lastTimestamp = chartData[chartData.length - 1]?.[0] || 0;
    const futureTimestamp = lastTimestamp + 10000; // 10 seconds in the future

    const options = {
      chart: {
        type: "spline",
        backgroundColor: "#131722",
        height: "400px",
        marginRight: 10,
        marginLeft: 0,
        marginBottom: 30,
        marginTop: 10,
        animation: Highcharts.svg,
      },
      title: null,
      xAxis: {
        type: "datetime",
        lineColor: "#2a2e39",
        tickColor: "#2a2e39",
        labels: {
          style: { color: "#787b86", fontSize: "10px" },
          y: 20,
          formatter: function () {
            return moment(this.value).format("HH:mm:ss");
          },
        },
        tickLength: 0,
        minPadding: 0,
        maxPadding: 0,
        gridLineWidth: 1,
        gridLineColor: "#2a2e39",
        tickInterval: 10000, // 10 seconds interval
        tickAmount: 6,
        min: lastTimestamp - 50000, // Show 50 seconds of past data
        max: futureTimestamp, // Extend to 10 seconds in the future
        plotLines: [
          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.startTime
              ? moment(startedRoundData?.startTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              useHTML: true, // Allows for custom HTML
              align: "center",
              y: 0,
              x: 0,
              formatter: function () {
                return `
                      <div class="custom-plotline-label">
                        <span class="label-text">Current</span>
                      </div>
                    `;
              },
            },
            events: {
              render: function () {
                // Access and style after rendering
                const plotLineLabel = this.plotLinesAndBands[0].label.element;
                plotLineLabel.style.transform = "rotate(270deg)";
                plotLineLabel.style.transformOrigin = "100% 12px";
                plotLineLabel.style.position = "absolute";
                plotLineLabel.style.left = "150px";
                plotLineLabel.style.top = "10px";
              },
            },
          },

          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.lockTime
              ? moment(startedRoundData?.lockTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              text: "End",
              align: "center",
              style: { color: "#ffffff", fontSize: "12px" },
              y: 15,
            },
          },
        ],
      },
      yAxis: {
        title: null,
        labels: {
          align: "right",
          x: 45,
          style: { color: "#787b86", fontSize: "10px" },
          formatter: function () {
            return this.value.toFixed(2);
          },
        },
        gridLineColor: "#2a2e39",
        gridLineWidth: 1,
        tickAmount: 5,
        opposite: true,
        plotLines: [
          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.startTime
              ? moment(startedRoundData?.startTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              text: startedRoundData?.startPrice
                ? startedRoundData?.startPrice
                : null,
              align: "center",
              style: {
                color: "#ffffff",
                fontSize: "12px",
                whiteSpace: "nowrap", // To ensure the text doesn't break
              },
              y: 15,
            },
          },
        ],
      },
      legend: { enabled: false },
      series: [
        {
          name: "Price",
          data: chartData,
          color: "#00ff00",
          lineWidth: 2,
          marker: {
            enabled: false,
          },
        },
      ],
      tooltip: {
        enabled: false,
      },
      credits: { enabled: false },
      plotOptions: {
        spline: {
          animation: {
            duration: 1000,
            easing: "easeOutQuart",
          },
        },
      },
    };

    setChartOptions(options);
  }, [data]);

  useEffect(() => {
    if (chartOptions.series) {
      const chart = Highcharts.charts[0];
      if (chart) {
        const series = chart.series[0];
        const lastPoint = series.data[series.data.length - 1];
        if (lastPoint) {
          lastPoint.update(
            {
              marker: {
                enabled: true,
                radius: 5,
                symbol: "circle",
                fillColor: "#00ff00",
                lineColor: "#00ff00",
                lineWidth: 2,
                states: {
                  hover: {
                    enabled: true,
                    radius: 5,
                    fillColor: "#00ff00",
                    lineColor: "#00ff00",
                    lineWidth: 2,
                  },
                },
              },
            },
            false
          );
          chart.redraw();
        }
      }
    }
  }, [chartOptions]);

  return (
    <div className="bg-[#131722] p-4 rounded-lg h-[485px]">
      <HighchartsReact highcharts={Highcharts} options={chartOptions} />
    </div>
  );
};

export default Chart;

javascript reactjs highcharts
1个回答
0
投票
最好的解决方案是使用带有自定义形状的注释和没有标签的绘图线。例如:

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>


Highcharts.SVGRenderer.prototype.symbols.customArrow = function (x, y, w, h) { return ['M', x, y, 'L', x + w, y, x + w, y + h, x, y + h, x - 10, y +h / 2, 'z']; };


现场演示:https://stackblitz.com/edit/react-cfh7pt?file=index.js,style.css

API 参考: https://api.highcharts.com/highcharts/annotations

文档: https://www.highcharts.com/docs/advanced-chart-features/annotations-module

© www.soinside.com 2019 - 2024. All rights reserved.