Search code examples
javascripthighchartsdraw

draw a dynamic circle with two arrow with hightcharts between two pont : actual real date and some (x,y) point


I use hightcharts with angular ,

i need to draw a dynamic circle that has as start (x,y) point until the actual date axe.

My angular ts code :

`xAxis: {`
`type: 'datetime',`
`lineWidth: 0,`
`tickPositions: [...this.tickPositions],`
`labels: {`
`x: 0,`
`y: chartStyles.y,`

          formatter(): any {
            //@ts-ignore
            let dateLabel = Highcharts.dateFormat('%H:%M',new Date(this.value));
    
            //@ts-ignore
            return (
              '\<span style="width:10px; height:24px; color:var(--chart-text-color); background-color: var(--rectangle-bg-color);  padding: 3px 4px;margin-top:90px; margin-bottom:10px; border-radius:4px;"\>' +
              dateLabel +
              '\</span\>'
            );
          },
          useHTML: true,
        },
    
        min: this.slotsStart(),
        max: this.slotsEnd(),
        gridLineColor: '#e6e6e6',
        gridLineWidth: 0.5,
        plotLines: \[
          {
            name: 'Current Time',
            color: 'var(--default-text-color)',
            width: 2,
            value: this.getCurrentDate(),
            zIndex: 6,
            label: {
              text: \`${this.getUTCRealtimeFormatedDate()}\`,
              align: 'bottom',
              x: -22,
              y: 287,
              enabled: true,
              rotation: 0,
              formatter() {
                //@ts-ignore
                return '\<span style="display: inline-block;color:var(--chart-text-color); background-color: var(--rectangle-bg-color);padding: 3px 4px;border-radius:4px;"\>' +Highcharts.dateFormat('%H:%M', new Date(this.options.value)) +'\</span\>'
                
              },
              useHTML: true,
            } as any,
          },
        \],
      },
    
      yAxis: {
        lineWidth: 0,
        gridLineDashStyle: 'longdash',
        gridLineColor: 'var(--chart-row-color)',
        max: 45,
        min: 0,
        title: {
          text: '',
        },
        labels: {
          x: -5,
          y: 8,
    
          formatter() {
            return (
              '\<span style="width:20px; height:24px; color:var(--chart-text-color); background-color: var(--frame-color); padding: 3px 6px; margin-bottom:10px; border-radius:4px;"\>' +
              this.value +
              '\</span\>'
            );
          },
          useHTML: true,
        } as any,
      },
    
      series: this.series,

draw betwwen the actual date ( real time , change every second ) and other fixed ime point (Xtimestemps,Yvalue) a circle with two arrow ( the arrow length change horizontally independent of those two point (fixed point , changed point)


Solution

  • You can create labels or shapes using Highcharts.SVGRenderer. Perform the drawing within the chart's render() event to ensure responsiveness. Additionally, you can identify the points of interest by accessing them from this event.

    Here's a simplified example for your reference:

      chart: {
        events: {
          render: function() {
            let chart = this,
              series = chart.series[0],
              points = series.points,
              lastPoint = points[points.length - 1],
              previousPoint = points[points.length - 2],
              xAxis = chart.xAxis[0],
              yAxis = chart.yAxis[0],
              x1 = xAxis.toPixels(previousPoint.x),
              y1 = yAxis.toPixels(previousPoint.y),
              x2 = xAxis.toPixels(lastPoint.x),
              y2 = yAxis.toPixels(lastPoint.y),
              arrowSize = 10,
              labelX = (x1 + x2) / 2,
              labelY = (y1 + y2) / 2;
    
            if (!chart.label) {
              chart.label = chart.renderer.label('Label')
                .attr({
                  r: 10,
                  stroke: 'gray',
                  fill: 'green',
                  'stroke-width': 1,
                  zIndex: 40,
                })
                .css({
                  color: 'white'
                })
                .add();
            }
    
            chart.label.attr({
              x: labelX - chart.label.width / 2,
              y: labelY - chart.label.height / 2
            });
    
            if (chart.arrows) {
              chart.arrows.forEach(arrow => arrow.destroy());
            }
    
            chart.arrows = [
              chart.renderer.path(['M', labelX, labelY, 'L', x1, labelY, 'M', x1 + 10, labelY - 10, 'L', x1, labelY, 'L', x1 + 10, labelY + 10]).attr({
                'stroke-width': 5,
                stroke: 'green',
                zIndex: 2
              }).add(),
              chart.renderer.path(['M', labelX, labelY, 'L', x2, labelY, 'M', x2 - 10, labelY - 10, 'L', x2, labelY, 'L', x2 - 10, labelY + 10]).attr({
                'stroke-width': 5,
                stroke: 'green',
                zIndex: 2
              }).add()
            ];
          }
        }
      },
    

    Demo: https://jsfiddle.net/BlackLabel/g3Lpk7a4/

    API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer https://api.highcharts.com/highcharts/chart.events.render