Koos
Koos

Reputation: 289

SVG marker on Highcharts path

I want to draw arrows on my Highcharts chart and came up with this so far. Looks nice but has problems:

If I could use a SVG marker on a Highcharts path like in this SVG tutorial drawing arrows would become much easier

My code:

  renderer.path(['M', 200, 0, 'L', 200, 200,'L', 225, 200,'L',200,250,'L', 175, 200,'L', 200, 200])
    .attr({
        'stroke-width': 5,
        stroke: 'red',fill:'red'
    })
    .add();
renderer.path(['M', 400, 0, 'L', 400, 200,'L', 425, 200,'L',400,250,'L', 375, 200,'L', 400, 200])
    .attr({
        'stroke-width': 50,
        stroke: 'red',fill:'red'
    })
    .add();

Upvotes: 0

Views: 1558

Answers (1)

Koos
Koos

Reputation: 289

I managed to draw arrows without using SVG marker. The arrow points exactly to the right spot, regardless of the rotation. It can even take into account the radius of the start and end point.

enter image description here

See fiddle

  function drawArrow(startX, startY, startRadius, endX, endY, endRadius, width) {

    var angle = Math.PI + Math.atan((endX - startX) / (endY - startY)),
        arrowLength = 3 * width,
        arrowWidth = 1.5 * width,
        path = [],
        startArrowX,
        startArrowY,
        margin = 5;

    if (endY >= startY) {
        //correct for circle radius
        startX -= ((startRadius + margin) * Math.sin(angle));
        startY -= ((startRadius + margin) * Math.cos(angle));
        endX += ((endRadius + margin) * Math.sin(angle));
        endY += ((endRadius + margin) * Math.cos(angle));

        //correct for arrow head length
        endX += (arrowLength * Math.sin(angle));
        endY += (arrowLength * Math.cos(angle));

        //draw arrow head
        path.push('M', endX, endY);
        path.push(
            'L',
        endX - arrowWidth * Math.cos(angle),
        endY + arrowWidth * Math.sin(angle));
        path.push(
        endX - arrowLength * Math.sin(angle),
        endY - arrowLength * Math.cos(angle));
        path.push(
        endX + arrowWidth * Math.cos(angle),
        endY - arrowWidth * Math.sin(angle), 'Z');
    } else {
        //correct for circle radius
        startX += ((startRadius + margin) * Math.sin(angle));
        startY += ((startRadius + margin) * Math.cos(angle));
        endX -= ((endRadius + margin) * Math.sin(angle));
        endY -= ((endRadius + margin) * Math.cos(angle));

        //correct for arrow head length
        endX -= (arrowLength * Math.sin(angle));
        endY -= (arrowLength * Math.cos(angle));

        //draw arrow head
        path.push('M', endX, endY);
        path.push(
            'L',
        endX + arrowWidth * Math.cos(angle),
        endY - arrowWidth * Math.sin(angle));
        path.push(
        endX + arrowLength * Math.sin(angle),
        endY + arrowLength * Math.cos(angle));
        path.push(
        endX - arrowWidth * Math.cos(angle),
        endY + arrowWidth * Math.sin(angle), 'Z');

    }

    renderer.path(path)
        .attr({
        'stroke-width': 1,
        stroke: '#989898',
        fill: '#989898'
    }).add();
    renderer.path(['M', startX, startY, 'L', endX, endY])
        .attr({
        'stroke-width': width,
        stroke: '#989898'
    }).add();

Upvotes: 3

Related Questions