Не отображаются линии на форме

Написал код для отрисовки связей в виде графа, но линии не отрисовываются. Более того, в строках linkText.attr("x", function (d) { return (d.source.x + d.target.x) / 2; }).attr("y", function (d) { return (d.source.y + d.target.y) / 2; }); в значениях x и y undefined. С чем может быть связана проблема?

p.s. коллекцию links и nodes передаю из ViewModel.

js:

var svg = d3.select("svg");
var width = + svg.attr("width");
var height = + svg.attr("height");

var simulation = d3
    .forceSimulation()
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2))
    .force("x", d3.forceX(width / 2))
    .force("y", d3.forceY(height / 2))
    .nodes(graphData.nodes)
    .on("tick", ticked);

var nodes = svg
    .append("g")
    .selectAll("circle")
    .data(graphData.nodes)
    .enter()
    .append("circle")
    .attr("r", 10)
    .attr("fill", "red");
    
var links = svg
    .append("g")
    .selectAll("line")
    .data(graphData.links)
    .enter()
    .append("line")
    .attr("stroke-width", 3)
    .style("stroke", "orange");

var linkText = svg
    .append("g")
    .selectAll("text")
    .data(graphData.links)
    .enter()
    .append("text")
    .text(d => d.name);

var drag = d3
    .drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended);

nodes.call(drag);

function ticked() {
    links.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; });
        
    linkText.attr("x", function (d) { return (d.source.x + d.target.x) / 2; })
            .attr("y", function (d) { return (d.source.y + d.target.y) / 2; });

    nodes.attr("cx", function (d) { return d.x; })
         .attr("cy", function (d) { return d.y; });
}

function dragstarted(d) {
    simulation.alphaTarget(0.3).restart();
    d.fx = d3.event.x;
    d.fy = d3.event.y;
}

function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
}

function dragended(d) {
    simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}

cshtml:

@using System.Text.Json
@model Server.ViewModels.NodeGraphViewModel

<!DOCTYPE html>
<meta charset="utf-8" />
<svg id="graph" width="500" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="/js/nodegraph.js" defer></script>
<script>
    var graphData = @Html.Raw(JsonSerializer.Serialize(Model.Graph));
</script>
<body>

</body>

ViewModel:

public class NodeGraphViewModel
{
    public GraphModel Graph { get; }

    public NodeGraphViewModel(GraphModel graph)
    {
        Graph = graph;
    }
}

GraphModel:

[Serializable]
public class GraphModel
{
    [JsonPropertyName("nodes")]
    public List<NodeModel> Nodes { get; set; } = [];

    [JsonPropertyName("links")]
    public List<LinkModel> Links { get; set; } = [];

    public GraphModel(IEnumerable<NodeModel> nodes, IEnumerable<LinkModel> links)
    {
        foreach (var node in nodes)
            Nodes.Add(node);

        foreach (var link in links)
            Links.Add(link);
    }
}

NodeModel:

[Serializable]
public class NodeModel
{
    [JsonPropertyName("name")]
    public string Name { get; set; }

    public NodeModel(string name)
    {
        Name = name;
    }
}

LinkModel:

[Serializable]
public class LinkModel
{
    [JsonPropertyName("source")]
    public string Source { get; set; }

    [JsonPropertyName("target")]
    public string Target { get; set; }

    public LinkModel(NodeModel source, NodeModel target)
    {
        Source = source.Name;
        Target = target.Name;
    }
}

Controller:

[HttpGet(nameof(NodeGraphPage))]
public async Task<ActionResult> NodeGraphPage()
{
    var nodes = new List<NodeModel>()
    {       
        new NodeModel("A"),
        new NodeModel("B"),
        new NodeModel("C"),
        new NodeModel("D")
    };
    var links = new List<LinkModel>()
    {
        new LinkModel(nodes.ElementAt(0), nodes.ElementAt(1)),
        new LinkModel(nodes.ElementAt(1), nodes.ElementAt(2)),
        new LinkModel(nodes.ElementAt(2), nodes.ElementAt(3))
    };

    var graphData = new GraphModel(nodes, links);

    var vm = new NodeGraphViewModel(graphData);
    return View("~/Views/nodegraph.cshtml", vm);
}

Ответы (0 шт):