Interactive Network Visualization with Highcharts Arrow Connections

I've been working on creating a network graph using Highcharts. Here's the chart I have so far:

https://i.sstatic.net/XbkF3.png

However, I'm struggling to find a way to add arrows instead of just line segments connecting the nodes in the Highcharts network graph module. Is there a way to achieve this with Highcharts? If not, are there any better alternatives that you would recommend for this specific use case? Below is the code snippet I am currently using to generate the network graph.

    eventWorkflowGraph = Highcharts.chart('graph-canvas', {
    chart: {
        type: 'networkgraph',
        spacingBottom: 15,
        spacingTop: 15,
        spacingLeft: 15,
        spacingRight: 15,
    },
    title: {
        text: 'Workflow'
    },
    subtitle: {
        text: 'Network Graph'
    },
    plotOptions: {
        networkgraph: {
            keys: ['from', 'to'],
            layoutAlgorithm: {
                friction: -0.9,
                linkLength: 100,
                enableSimulation: true
            },
            link: {
                width: 4
            }
        }
    },
    series: [{
        dataLabels: {
            enabled: true,
            linkFormat: '',
        },
        marker: {
            radius: 45
        },
        data: edges
    }]
});

This results in the following network graph visualization: https://i.sstatic.net/GPYfU.png

Answer №1

Here is a solution to render arrows at the end of links in the networkgraph series based on feedback.

To see a live demonstration, click here: https://jsfiddle.net/BlackLabel/cnjw7v2s/

(function(H) {
  H.wrap(H.seriesTypes.networkgraph.prototype.pointClass.prototype, 'getLinkPath', function(p) {
    var left = this.toNode,
      right = this.fromNode;

    var angle = Math.atan((left.plotX - right.plotX) /
      (left.plotY - right.plotY));


    if (angle) {
      let path = ['M', left.plotX, left.plotY, right.plotX, right.plotY],
        lastPoint = left,
        nextLastPoint = right,
        pointRadius = 45,
        arrowLength = 20,
        arrowWidth = 10;

      if (left.plotY < right.plotY) {
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle) - arrowLength * Math.sin(angle) - arrowWidth * Math.cos(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle) - arrowLength * Math.cos(angle) + arrowWidth * Math.sin(angle),
        );

        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX - pointRadius * Math.sin(angle) - arrowLength * Math.sin(angle) + arrowWidth * Math.cos(angle),
          nextLastPoint.plotY - pointRadius * Math.cos(angle) - arrowLength * Math.cos(angle) - arrowWidth * Math.sin(angle),
        );


      } else {
        path.push(
          nextLastPoint.plotX + pointRadius * Math.sin(angle),
          nextLastPoint.plotY + pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX + pointRadius * Math.sin(angle) + arrowLength * Math.sin(angle) - arrowWidth * Math.cos(angle),
          nextLastPoint.plotY + pointRadius * Math.cos(angle) + arrowLength * Math.cos(angle) + arrowWidth * Math.sin(angle),
        );
        path.push(
          nextLastPoint.plotX + pointRadius * Math.sin(angle),
          nextLastPoint.plotY + pointRadius * Math.cos(angle),
        );
        path.push(
          nextLastPoint.plotX + pointRadius * Math.sin(angle) + arrowLength * Math.sin(angle) + arrowWidth * Math.cos(angle),
          nextLastPoint.plotY + pointRadius * Math.cos(angle) + arrowLength * Math.cos(angle) - arrowWidth * Math.sin(angle),
        );

      }

      return path
    }
    return [
      ['M', left.plotX || 0, left.plotY || 0],
      ['L', right.plotX || 0, right.plotY || 0],
    ];
  });
}(Highcharts));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to turn the visible section of a PNG image with a transparent background into a clickable link?

I wanted to link a .png image with a transparent background on my website. After trying the following HTML: <a href="index.html"> <img border="0" src="smiley.png" alt="smiley" width="150" height="150"> </a> and CSS: a { text-d ...

Having trouble implementing render props for a toggle button that reveals/hides child components

My goal is to display or hide a couple of child components based on a toggle click using the original HTML structure provided. However, I am encountering an issue where the EditToggle link needs to be displayed next to the h2 element inside the "subtitle-c ...

Creating a responsive Youtube video that is perfectly centered on a web page

Currently, I am working on embedding a responsive Youtube video. I have managed to make it responsive using code that I found online. However, I am facing an issue where the height of the video does not adjust to 100% when the width is small. I want the he ...

JavaScript: retrieving undefined value from a text element

My goal is to retrieve the text entered into each textbox by querying and looping through their ID tags. However, when I attempt to print what I have retrieved, it always displays "undefined". Seems like your post consists mostly of code: </h ...

Using the linearGradient feature within an SVG to create a transitional effect on the Fill property

Looking to implement a stepper functionality, everything is working smoothly except for the transition on the fill. let step = 0; document.querySelector("button").addEventListener('click', () => { step++; document.querySelector("svg ...

Struggling with setting up mustache.js to show data on the website

I'm having some trouble using mustache js to show a list of employee names on a website. I seem to be missing something because when I go to the webpage, nothing shows up. Can someone please help me figure out how to make the employee information appe ...

What's up with the Twitter Bootstrap parameters?

As a beginner in the world of HTML5 and Twitter Bootstrap, I have been exploring some pre-built examples and now have a few questions... Consider this code snippet from the Fluid Layout Example: <div class="navbar navbar-fixed-top"> <div class ...

Webkit causing complications with straightforward CSS3 animation

I'm currently working on a website and you can check it out here: Unfortunately, I've encountered an issue where the animations aren't triggering specifically on webkit browsers like Chrome and Safari: @-webkit-keyframes slideright{ 0% {tr ...

Obtain and showcase the index of the checkbox that has been selected

Is there a way to display the position of a checkbox when it is checked using JQuery? For instance, if Monday is checked, it should display position 0 and if Sunday is checked, it should show position 6. I have tried using .index() but it keeps returning 0 ...

Change the CoreUI variable by overriding it

There's a fantastic gem called https://github.com/pelted/coreui-rails that utilizes CoreUI, a Bootstrap Admin Template. This template has replaced the default Bootstrap colors, and I am attempting to customize them back to my preferred colors, specif ...

Incapable of smoothly scrolling through individual div tags

I am facing an issue with my ajax page (search.js) attached to my main page that runs a setInterval every 2 seconds. On the main page, I have a div tag (class="view") that can slide down and interrupt the interval. Everything is working fine except when I ...

What is the Best Way to Send Multiple Values using a Single Submit Button?

Hello, I am working on a website where users can send emails to each other. However, I am facing an issue with the submission process - it is not submitting both values at the same time. My form consists of a text box for the email address and a text ...

Create a spectrum of vibrant colors depending on the numerical value

I'm attempting to create a function that generates rainbow colors based on a numerical value. var max = 10000; var min = 0; var val = 8890; function getColor(min, max, val) { // code to return color between red and black } Possible Colors: Re ...

Enhance Your Website with WordPress and Facebook Integration (requires understanding of PHP)

I was able to retrieve the number of Facebook comments using this function: <?php function fb_comment_count() { global $post; $url = get_permalink($post->ID); $filecontent = file_get_contents('https://graph.facebook.com/?ids=' . $url) ...

CSS and the art of absolute positioning

My grasp of CSS positioning was solid until I stumbled upon this straightforward code snippet (also available in JSFiddle). #outer { /*position: absolute;*/ box-shadow: inset 0 0 3px red; } #inner { box-shadow: inset 0 0 3px blue; /*position: ab ...

Set up a listener to detect changes in fullscreen mode for the specified host

How can I determine if the fullscreen mode is active using the HTML5 fullscreen API with Chrome and Angular 4.x? I have developed an Angular component and included the following @HostListener: @HostListener('document:webkitfullscreenchange', ...

Is there a faster way to sort this data with Javascript (or JQuery for extra speed)?

Recently, I've encountered a challenge with sorting an HTML table using JavaScript. The table can potentially contain over a thousand rows. This is what my current setup looks like in terms of HTML: <div id="mycollection" class="table"> &l ...

Creating an intelligent autocomplete feature in JavaScript that recognizes the . character as a wildcard for matching any character

I found this code and would like to enhance its functionality. For instance, when I search for ".an.d", I want the code to display all words that have an "a" at the second position, "n" at the third position, any character at the fourth position, and "d" ...

Using PHP regular expressions to find the final occurrence trailing after the last match in HTML

Looking to analyze a webpage (where the same product price is compared on different stores - each store has a block with its logo, price...) I want to separate each store into a different array element using preg_match_all I am trying to skip the advert ...

Populate the content of the child DIV to match the grid layout as a whole

I am attempting to control the layout of the grid on my website using CSS. By utilizing Bootstrap 4, I have created two divs with equal height using display:grid. However, I am facing difficulties in managing the child elements within these divs. I am tryi ...