How can I dynamically populate an undirected graph with C# classes using JavaScript in Razor pages?

25 views Asked by At

I need some help in dynamically providing data to my undirected graph. I want to use classes that are written in C# for the links and nodes. The visual representation is done in JavaScript inside a Razor page.

This is what I have tried until now, but without success.

This is my Link class:

public class Link
    {
        public int Source { get; set; }
        public int Target { get; set; }
        public int Weight { get; set; }

        public Link(int source, int target, int weight)
        {
            Source = source;
            Target = target;
            Weight = weight;
        }
    }

This is my Node class:

public class Node
    {
        public int Id { get; set; }
        public string Label { get; set; }

        public Node(int id, string label)
        {
            Id = id;
            Label = label;
        }
    }

This is the Page Model:

public class GraphTestingModel : PageModel
    {
        public string GraphData { get; private set; }

        public void OnGet()
        {

            var nodes = GetNodes();
            var links = GetLinks();

            // Create a data object to hold the nodes and links
            var data = new
            {
                nodes = nodes,
                links = links
            };

            // Serialize the data object to JSON
            GraphData = JsonConvert.SerializeObject(data);
        }

        private List<Node> GetNodes()
        {
            // Create and populate the list of nodes
            var nodes = new List<Node>
        {
            new Node(0, "Myriel"),
            new Node(1, "Napoleon"),
            new Node(2, "MlleBaptistine"),
            new Node(3, "MmeMagloire"),
            new Node(4, "CountessDeLo"),
            new Node(5, "Geborand"),
            new Node(6, "Champtercier"),
            new Node(7, "Cravatte"),
            new Node(8, "Count"),
            new Node(9, "OldMan"),
            new Node(10, "Labarre"),
        };

            return nodes;
        }

        private List<Link> GetLinks()
        {
            // Create and populate the list of links
            var links = new List<Link>
        {
            new Link(1, 0, 1),
            new Link(2, 0, 8),
            new Link(3, 0, 10),
            new Link(3, 2, 6),
            new Link(4, 0, 1),
            new Link(5, 0, 1),
            new Link(6, 0, 1),
            new Link(7, 0, 1),
            new Link(8, 0, 2),
            new Link(9, 0, 1)
        };

            return links;
        }
    }

This is the View of the page:

<head>
    <meta charset="UTF-8">
    <title>Spider Diagram</title>
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <style>
        svg {
            font: 10px sans-serif;
        }

        .link {
            stroke: #999;
            stroke-opacity: 0.6;
        }

        .node circle {
            fill: #fff;
            stroke: steelblue;
            stroke-width: 1.5px;
        }

        .node text {
            font-size: 12px;
        }
    </style>
</head>
<body>
    <div id="graph"></div>

    <script>
        var data = @Html.Raw(Model.GraphData);
        console.log(data);
        var width = 960,
            height = 500,
            radius = 6;

        var force = d3.layout.force()
            .gravity(.05)
            .charge(-120)
            .linkDistance(80)
            .size([width, height]);

        var svg = d3.select("#graph").append("svg")
            .attr("width", width)
            .attr("height", height);
        var color = d3.scale.category20();

        force
            .nodes(data.nodes)
            .links(data.links)
            .start();

        var link = svg.selectAll(".link")
            .data(data.links);

        var node = svg.selectAll(".node")
            .data(data.nodes);

        node.exit().remove();
        link.exit().remove();

        link.enter().append("line")
            .attr("class", "link")
            .style("stroke-width", function (d) {
                if ("value" in d) {
                    return Math.sqrt(d.value);
                } else {
                    return 1;
                }
            });

        var groups = node.enter()
            .append("g")
            .attr("class", "node");

        groups.append("circle").attr("r", function (d) {
            if ("id" in d) { return 5; }
            else { return 0; }
        })
            .style("fill", function (d) { return color(d.value); })
            .call(force.drag);

        groups.append("text")
            .attr("dx", 12)
            .attr("dy", ".35em")
            .text("hi");

        node.selectAll("text")
            .text(function (d) {
                if ("label" in d) {
                    return d.label;
                } else {
                    return d.id;
                }
            }
            );

        force.on("tick", function () {
            link.attr("x1", function (d) {
                return d.source.x;
            })
                .attr("y1", function (d) {
                    return d.source.y;
                })
                .attr("x2", function (d) {
                    return d.target.x;
                })
                .attr("y2", function (d) {
                    return d.target.y;
                });

            node.attr("cx", function (d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
                .attr("cy", function (d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
            node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
        });
    </script>
</body>

Note that what I tried here is still not 'dynamically' populating the graph with data, but an attempt to gradually work up to it. I have thought about why this might not work and I think it has something to do with the way the data is serialized, but I have no clue how to fix this. Also, the documentation didn't really help me solving the issue

0

There are 0 answers