如何在Highcharts的折线图上绘制箭头?

时间:2016-07-15 09:45:27

标签: javascript highcharts

我正在尝试在Highcharts折线图的末尾添加箭头。我已经浏览了similar questions,但解决方案似乎不起作用:

我正在寻找的结果(添加颜色),

enter image description here

5 个答案:

答案 0 :(得分:3)

您应该包装drawGraph方法并添加箭头代码。它可以通过路径方法实现。

{{1}}

示例:

答案 1 :(得分:2)

<强>(UPDATE)

之前的解决方案反应不太明显,因为它会在调整浏览器大小时每次重绘图表上的箭头。

但是我发现如何使用箭头完全响应来制作图表:

(function(H) {

    var arrowCheck = false,
        pathTag;

    H.wrap(H.Series.prototype, 'drawGraph', function(proceed) {

    // Now apply the original function with the original arguments, 
    // which are sliced off this function's arguments

    proceed.apply(this, Array.prototype.slice.call(arguments, 1));

    var arrowLength = 15,
        arrowWidth = 9,
        series = this,
        data = series.data,
        len = data.length,
        segments = data,
        lastSeg = segments[segments.length - 1],
        path = [],
        lastPoint = null,
        nextLastPoint = null;

    if (lastSeg.y == 0) {
       lastPoint = segments[segments.length - 2];
       nextLastPoint = segments[segments.length - 1];
    } else {
       lastPoint = segments[segments.length - 1];
       nextLastPoint = segments[segments.length - 2];
    }

    var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
        (lastPoint.plotY - nextLastPoint.plotY));

    if (angle < 0) angle = Math.PI + angle;

    path.push('M', lastPoint.plotX, lastPoint.plotY);

    if (lastPoint.plotX > nextLastPoint.plotX) {

       if (arrowCheck === true) {

         pathTag = document.getElementById("arrow");
         if (pathTag != null) {
           pathTag.remove(pathTag);
       }
     }

     path.push(
        'L',
        lastPoint.plotX + arrowWidth * Math.cos(angle),
        lastPoint.plotY - arrowWidth * Math.sin(angle)
     );
     path.push(
        lastPoint.plotX + arrowLength * Math.sin(angle),
        lastPoint.plotY + arrowLength * Math.cos(angle)
     );
     path.push(
        lastPoint.plotX - arrowWidth * Math.cos(angle),
        lastPoint.plotY + arrowWidth * Math.sin(angle),
        'Z'
     );
    } else {     

       if (arrowCheck === true) {

          pathTag = document.getElementById("arrow");
          if (pathTag != null) {
             pathTag.remove(pathTag);
          }
       }

       path.push(
         'L',
         lastPoint.plotX - arrowWidth * Math.cos(angle),
         lastPoint.plotY + arrowWidth * Math.sin(angle)
       );
       path.push(
         lastPoint.plotX - arrowLength * Math.sin(angle),
         lastPoint.plotY - arrowLength * Math.cos(angle)
       );
       path.push(
         lastPoint.plotX + arrowWidth * Math.cos(angle),
         lastPoint.plotY - arrowWidth * Math.sin(angle),
         'Z'
       );

    }

    series.chart.renderer.path(path)
    .attr({
       fill: series.color,
       id: 'arrow'
    })
    .add(series.group);

    arrowCheck = true;

   });
}(Highcharts));

希望这会有所帮助。干杯!

答案 2 :(得分:2)

对我很有帮助!

注意,上面的代码只有在图表上只有一个系列时才有效。我做了一些改动,让它可以使用多个系列。问题在于,由于每个箭头具有相同的ID,因此会消除其他系列的先前箭头,认为它们是需要重绘的旧箭头。我所做的就是将id更改为&#39; arrow&#39;的组合。和系列名称,所以它只删除特定系列的先前箭头。

(function(H) {

    var arrowCheck = false,
        pathTag;

    H.wrap(H.Series.prototype, 'drawGraph', function(proceed) {

      // Now apply the original function with the original arguments, 
      // which are sliced off this function's arguments
      proceed.apply(this, Array.prototype.slice.call(arguments, 1));

      // used a bit of regex to clean up the series name enough to be used as an id
      var arrowName = "arrow"+this.name.replace(/\W/g,"_").toLowerCase();
      // console.log("----------->arrowName:"+arrowName)

      var arrowLength = 15,
        arrowWidth = 7,
        series = this,
        data = series.data,
        len = data.length,
        segments = data,
        lastSeg = segments[segments.length - 1],
        path = [],
        lastPoint = null,
        nextLastPoint = null;

      if (lastSeg.y == 0) {
        lastPoint = segments[segments.length - 2];
        nextLastPoint = segments[segments.length - 1];
      } else {
        lastPoint = segments[segments.length - 1];
        nextLastPoint = segments[segments.length - 2];
      }

      var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
        (lastPoint.plotY - nextLastPoint.plotY));

      if (angle < 0) angle = Math.PI + angle;

      path.push('M', lastPoint.plotX, lastPoint.plotY);

      if (lastPoint.plotX > nextLastPoint.plotX) {

        if (arrowCheck === true) {
          //replaced 'arrow' with arrowName
          pathTag = document.getElementById(arrowName);
          if (pathTag != null) {
            pathTag.remove(pathTag);
          }
        }

        path.push(
          'L',
          lastPoint.plotX + arrowWidth * Math.cos(angle),
          lastPoint.plotY - arrowWidth * Math.sin(angle)
        );
        path.push(
          lastPoint.plotX + arrowLength * Math.sin(angle),
          lastPoint.plotY + arrowLength * Math.cos(angle)
        );
        path.push(
          lastPoint.plotX - arrowWidth * Math.cos(angle),
          lastPoint.plotY + arrowWidth * Math.sin(angle),
          'Z'
        );
      } else {


        if (arrowCheck === true) {
          //replaced 'arrow' with arrowName
          pathTag = document.getElementById(arrowName);
          if (pathTag != null) {
            pathTag.remove(pathTag);
          }
        }

        path.push(
          'L',
          lastPoint.plotX - arrowWidth * Math.cos(angle),
          lastPoint.plotY + arrowWidth * Math.sin(angle)
        );
        path.push(
          lastPoint.plotX - arrowLength * Math.sin(angle),
          lastPoint.plotY - arrowLength * Math.cos(angle)
        );
        path.push(
          lastPoint.plotX + arrowWidth * Math.cos(angle),
          lastPoint.plotY - arrowWidth * Math.sin(angle),
          'Z'
        );
      }

      series.chart.renderer.path(path)
        .attr({
          fill: series.color,
          id: arrowName //changed from 'arrow' to arrowName to enable more than one series with an arrow
        })
        .add(series.group);

       arrowCheck = true;

    });
  }(Highcharts));

答案 3 :(得分:0)

使用两个系列

来修复/清理jmfeland的答案版本

http://jsfiddle.net/vyfsf1ft/18/

$(function() {

  (function(H) {
    var arrowCheck = false
    var pathTag

    H.wrap(H.Series.prototype, 'drawGraph', function(proceed) {
      // Apply the original function with the original arguments,
      // which are sliced off this function's arguments
      var series = this
      proceed.apply(series, Array.prototype.slice.call(arguments, 1))

      var arrowName = 'arrow' + series.name.replace(/\W/g, '_').toLowerCase()
      var arrowLength = 15
      var arrowWidth = 7
      var data = series.data
      var len = data.length
      var lastSeg = data[len - 1]
      var path = []
      var lastPoint = null
      var nextLastPoint = null

      if (lastSeg.y == 0) {
        lastPoint = data[len - 2]
        nextLastPoint = data[len - 1]
      } else {
        lastPoint = data[len - 1]
        nextLastPoint = data[len - 2]
      }

      var angle = Math.atan((lastPoint.plotX - nextLastPoint.plotX) /
        (lastPoint.plotY - nextLastPoint.plotY))

      if (angle < 0) angle = Math.PI + angle

      path.push('M', lastPoint.plotX, lastPoint.plotY)

      if (lastPoint.plotX > nextLastPoint.plotX) {
        if (arrowCheck === true) {
          pathTag = document.getElementById(arrowName)
          if (pathTag != null) {
            pathTag.remove(pathTag)
          }
        }

        path.push(
          'L',
          lastPoint.plotX + arrowWidth * Math.cos(angle),
          lastPoint.plotY - arrowWidth * Math.sin(angle)
        )
        path.push(
          lastPoint.plotX + arrowLength * Math.sin(angle),
          lastPoint.plotY + arrowLength * Math.cos(angle)
        )
        path.push(
          lastPoint.plotX - arrowWidth * Math.cos(angle),
          lastPoint.plotY + arrowWidth * Math.sin(angle),
          'Z'
        )
      } else {
        if (arrowCheck === true) {
          pathTag = document.getElementById(arrowName)
          if (pathTag != null) {
            pathTag.remove(pathTag)
          }
        }

        path.push(
          'L',
          lastPoint.plotX - arrowWidth * Math.cos(angle),
          lastPoint.plotY + arrowWidth * Math.sin(angle)
        )
        path.push(
          lastPoint.plotX - arrowLength * Math.sin(angle),
          lastPoint.plotY - arrowLength * Math.cos(angle)
        )
        path.push(
          lastPoint.plotX + arrowWidth * Math.cos(angle),
          lastPoint.plotY - arrowWidth * Math.sin(angle),
          'Z'
        )
      }

      series.chart.renderer.path(path)
        .attr({
          fill: series.color,
          id: arrowName,
        })
        .add(series.group)

      arrowCheck = true
    })
  }(Highcharts))

  var chart = new Highcharts.Chart({
    chart: {
      renderTo: 'container',
      defaultSeriesType: 'scatter'
    },
    xAxis: {
      min: 0,
      max: 10
    },
    plotOptions: {
      series: {
        animation: {
          duration: 2000
        },
        lineWidth: 2,
        marker: {
          enabled: false
        }
      },
      states: {
        hover: {
          enabled: true,
          lineWidth: 2
        },
      }
    },
    series: [{
      name: 'main',
      id: 'main',
      data: [
        [0, 0],
        [3, 4]
      ]
    }, {
      name: 'secondary',
      id: 'secondary',
      data: [
        [1, 0],
        [5, 8]
      ]
    }]
  })
})

答案 4 :(得分:0)

(更新)曲线图XY

if (lastPoint.plotX > nextLastPoint.plotX || (lastPoint.plotX==nextLastPoint.plotX && lastPoint.plotY > nextLastPoint.plotY)) 

Grap Arrow Line XY