Reputation: 90
The code is based on Denise's one on bl.ocks. How can I add to the existing code text and an icon to a node? I have almost got it by appending the needed elements but the problem is that circles appear at (0, 0) coordinate.
A picture is worth a thousand words,
and my target is having inside the nodes and where the nodes need to be, a text in the middle and an icon,
This is my current code, that works perfectly as long as the commented part is not uncommented (that's what I have tried to do)
let translateVar = [0,0];
let scaleVar = 1;
let radius = 50;
function create_pan_zoomable_svg(html_element, width, height) {
let svg = d3.select("body")
.append("svg")
.attr("width", "100%")
.attr("height", "100%")
.style("background-color", "#eeeeee")
.call(_zoom).on("dblclick.zoom", null)
.append("g");
d3.select("#zoom_in").on('click', function() { _zoom.scaleBy(svg, 2)});
d3.select("#zoom_out").on('click', function() { _zoom.scaleBy(svg, 0.5)});
create_marker(svg);
initialize_link_node(svg);
return svg;
}
var _zoom = d3.zoom()
.on("zoom", function() {
translateVar[0] = d3.event.transform.x;
translateVar[1] = d3.event.transform.y;
scaleVar = d3.event.transform.k;
svg.attr('transform', 'translate(' + translateVar[0] + ',' + translateVar[1] + ') scale(' + scaleVar + ')');
});
function create_marker(svg) {
let defs = svg.append("defs");
defs.append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 40)
.attr("refY", 0)
.attr("markerWidth", 8)
.attr("markerHeight", 8)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
}
function getScreenInfo() {
return {
width : ($(window).width()-translateVar[0])/scaleVar,
height : ($(window).height()-translateVar[1])/scaleVar,
centerx : (($(window).width()-translateVar[0])/scaleVar)/2,
centery : (($(window).height()-translateVar[1])/scaleVar)/2
};
}
let link, node, simulation;
function initialize_link_node(svg) {
let currentScreen = getScreenInfo();
simulation = d3.forceSimulation()
.force("link", d3.forceLink()
.id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody()
.strength(function(d) { return -20000;}))
.force("center", d3.forceCenter(currentScreen.centerx, currentScreen.centery));
link = svg.append("g").selectAll(".link");
node = svg.append("g").selectAll(".node");
}
function spawn_nodes(svg, graph, around_node, filtering_options) {
node = node.data(theData.nodes, function(d) {
return d.id;
});
let newNode = node.enter().append("g");
newNode = newNode.append("circle")
.attr("class", "node")
.attr("r", radius)
.attr("fill", function(d) {
return colors[d.type]
})
.attr("id", function(d) {
return d.id
});
/****************************************************
newNode.append("text")
.text( function(d) {
return d.id;
})
.style("fill", "red")
.style("text-anchor", "middle");
newNode.append("svg:image")
.attr("href", function(d) {
return dict_type_icon[d.type];
}).attr("width", "30")
.attr("height", "30");**************************/
newNode.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
);
node = node.merge(newNode);
link = link.data(theData.edges, function(d) {
return d.id;
});
let newLink = link.enter().append("line").attr("class", "link").attr("marker-end", "url(#arrow)");
newLink.append("title").text(function(d) {
return d.labeled;
});
link = link.merge(newLink);
node = node.merge(newNode);
simulation.nodes(theData.nodes).on("tick", ticked);
simulation.force("link").links(theData.edges);
simulation.alpha(1).alphaTarget(0).restart();
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
function ticked() {
let currentScreen = getScreenInfo();
node
.attr("cx", function(d) {
return d.x = Math.max(radius, Math.min(currentScreen.width - radius, d.x));
})
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(currentScreen.height - radius, d.y)); });
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; });
}
When I uncomment the circles appear at (0,0) point as you may have seen in the image.
I would appreciate if you could help me! Thank you.
Upvotes: 2
Views: 661
Reputation: 102194
Right now, you're turning newNode
into a circles' selection:
newNode = newNode.append("circle")
//etc...
So, in order to keep it as a groups' selection, change that line to:
newNode.append("circle")
//etc...
Then, uncomment the commented part.
Finally, since that now node.merge(newNode)
will be a groups' selection, change the cx
and cy
in ticked function to translate
:
node.attr("transform", function(d) {
return "translate(" + (d.x = Math.max(radius, Math.min(currentScreen.width - radius, d.x))) +
"," + (d.y = Math.max(radius, Math.min(currentScreen.height - radius, d.y))) + ")";
});
Upvotes: 2