Не отображаются линии на форме
Написал код для отрисовки связей в виде графа, но линии не отрисовываются. Более того, в строках 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);
}