EDIT: It seems it is not easily possible to apply SemanticUI styles to SVG elements. The accepted answer provides corrections of the original code and some ideas for a workaround.
I'm quite new to web development. I'm trying to create a graph using d3.js, and I want the nodes to be styled according to the "ui button tiny blue" classes of the SemanticUI stylesheet. However, when I add this class to the nodes in the svg, they are not displayed all. Inspecting them in the browser tells me that the style has been applied properly, but the content box for some reason has negative height and width. The "TEST_NODE" outside the svg gets displayed as intended. What am I doing wrong?
The html document with inline js-script:
<!DOCTYPE html>
<meta charset="utf-8">
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj 3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v2.min.js?2.9.3"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
<style>
.link {
stroke: #aaa;
}
</style>
<body>
<div >
<div >TEST_NODE</div>
</div>
<script>
$(document).ready(function (){
var width = 960,
height = 500
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(.05)
.distance(100)
.charge(-100)
.size([width, height]);
d3.json("d3_test.json", function(json) {
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(json.nodes)
.enter()
.append("g")
.call(force.drag);
node.append("div")
.attr("class", "ui button tiny blue")
.text("NODE")
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("transform", function(d) { return "translate(" d.x "," d.y ")"; });
});
});
});
</script>
</body>
CodePudding user response:
Your code has 2 errors:
- Class is missing for the node elements. Fix it by:
const node = svg.selectAll(".node")
.data(json.nodes)
.enter()
.append("g")
.classed("node", true)
.call(force.drag);
- You cannot create a
<div>under<g>. You can append a<text>:
node.append('rect')
.attr('x', -50)
.attr('y', -30)
.attr('width', 100)
.attr('height', 60)
.style('fill', 'blue');
node.append('text')
.classed('ui ...', true)
.text('NODE')
.attr('alignment-baseline', 'middle')
.attr('text-anchor', 'middle')
.style('fill', 'white');
... or insert a <div> under a <foreignObject>;
