Reputation: 8905
I would like to draw few text box and chain it with arrow lines. I use below code to draw the text box few issues there:
test()
function test() {
var data = ["a","b","c","d","e"]
width = 800
height = 600
margin = 10
//var svg = d3.select("svg");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom);
svg.style("border","5px solid red");
svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var group = svg.selectAll('g')
.data(data).enter()
.append('g')
.attr('transform',function(d,i) {
//console.log(i,d);
return 'translate('+(100*i)+',0)';
});
var box = group.selectAll('rect')
.data(function(d) {
return d;
});
box.enter()
.append("rect")
.attr("width", 30)
.attr("height", 30)
.attr('font-size',2)
.attr("x", function(d, i) {
//console.log(d);
return 60 + 2*d;
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
Upvotes: 1
Views: 265
Reputation: 38211
You aren't appending any text. Text also can't be appended to a rectangle, so there is no need to apply font properties to a rectangle. Text can be appended to a g
though. So we can use a parent g
to hold both rectangle and text. Something like:
group.append("rect")...
group.append("text")...
The boxes are black because you haven't applied a fill. The default fill is black.
This is because when you enter the parent g
elements, you select all g
elements. This includes the one you've already appended (svg.append("g")
). The enter selection is intended to create elements such that every item in the data array is paired with an element in the DOM. Since you already have a g
in your selection, the enter selection will only create 4 new ones (representing data array items with indexes 1-4 but not 0).
Instead of selectAll("g")
you could specify a class name or, in the event you simply want to enter everything and there isn't a need to ever update a selection: selectAll(null)
. The latter option will always return an empty selection, which will result in the enter selection containing one element per item in the data array.
Note, that the parent's datum is passed to appended children automagically, there is no need to use the .data method to pass this onward unless you are handling nested data.
Here's a snippet addressing issues in one and two:
test()
function test() {
var data = ["a","b","c","d","e"]
width = 800
height = 600
margin = 10
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.style("border","5px solid red");
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var group = svg.selectAll(null)
.data(data).enter()
.append('g')
.attr('transform',function(d,i) {
return 'translate('+(40*i)+',0)';
});
group
.append("rect")
.attr("width", 30)
.attr("height", 30)
.attr("fill","yellow")
group.append("text")
.text(function(d) { return d; })
.attr("y", 20)
.attr("x", 15)
.attr("text-anchor","middle");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
I also changed svg
to refer to the parent g
, the one with the margin applied. Before the g
with the margin remained unused, along with the margin. I also modified the spacing to keep everything in view.
This can be done in many ways and really is a separate issue from the others, so I'll only quickly demonstrate one of many options. I'll modify your data structure a bit so that each datum has positional data and then add arrows using SVG markers:
test()
function test() {
var data = [{name:"a"},{name:"b"},{name:"c"},{name:"d"},{name:"e"}]
width = 800
height = 600
margin = 10
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.style("border","5px solid red")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs")
.append("marker")
.attr("id","pointer")
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient","auto")
.attr("refY", 5)
.append("path")
.attr("d", "M 0 0 L 10 5 L 0 10 z")
var group = svg.selectAll(null)
.data(data).enter()
.append('g')
.attr('transform',function(d,i) {
d.x = 40*i+15, d.y=30;
return 'translate('+(40*i)+',0)';
});
group
.append("rect")
.attr("width", 30)
.attr("height", 30)
.attr("fill","yellow")
group.append("text")
.text(function(d) { return d.name; })
.attr("y", 20)
.attr("x", 15)
.attr("text-anchor","middle");
links = [
{source: data[0], target: data[1]},
{source: data[0], target: data[2]}
]
svg.selectAll(null)
.data(links)
.enter()
.append("path")
.attr("d", function(d) {
var midX = (d.source.x+d.target.x)/2;
return "M"+d.source.x+" "+d.source.y+"Q"+midX+" "+200+" "+d.target.x+" "+(d.target.y+6);
})
.attr("fill","none")
.attr("stroke","black")
.attr("stroke-width",1)
.attr("marker-end","url(#pointer)");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
Upvotes: 2