I'm having a tough time figuring out how to place images inside a circle using links in my data set. I know a pattern is required to add images to nodes - related SO questions on this topic append the def, pattern and image elements before the introduction of nodes and data.
In my case, I couldn't find a way out of appending the tags inside the selector function because data is added dynamically to each node. Here's the code to the project, each black dot is supposed to contain a different image of an insect (url is in the tsv file): https://plnkr.co/edit/Ydrxogbfm9JvqrgeQaQ6?p=preview
I tried changing xlink:href
in the body tags with the code below:
<body>
<svg width="1000" height="600">
<defs id="mdef">
<pattern id="image" x="0" y="0" height="40" width="40">
<image x="0" y="0" width="40" height="40" ></image>
</pattern>
</defs>
</svg>
</body>
and this snippet of JS within the code block adding the nodes. :
.attr('"xlink:href", function(d){return d[1];}) //d is an array and the d[1] is the link
However, the images didn't appear. I then tried adding the pattern using js:
for (i=0;i<insects.length;i++){
g.selectAll("circle")
.data(insects[i],function(d) {console.log(d); return d }) //each insect
.enter().append("circle")
.attr('cx', function(d,index) {return x(insects[i].length)/insects[i].length*index; })
.attr("r", 20)
.attr("cy", function(d,index){return y.bandwidth()*i})
.append('svg:defs') //adding pattern
.append('svg:pattern')
.attr('id','pattern')
.attr("x",0)
.attr("y",0)
.attr("width",40)
.attr("height",40)
.append("svg:image")
.attr("x",0)
.attr("y",0)
.attr("width",40)
.attr("height",40)
.attr("xlink:href", function(d){console.log(d[1]); return d[1];})
.style("fill", "url(#pattern)");
}
})
But I get the same result. Would really appreciate any pointers as I'm a beginner in d3. Happy holidays
You cannot append a <defs>
, a <pattern>
and a <image>
to a circle. That won't work.
Instead of that, you have to create the <defs>
, append the patterns and images, and fill the circles according to their unique IDs:
var defs = g.append("defs");
defs.selectAll(".patterns")
.data(insects[i], function(d) {
return d
})
.enter().append("pattern")
.attr("id", function(d) {
return "insect" + (d[0].split(" ").join(""))
})
.attr("width", 1)
.attr("height", 1)
.append("svg:image")
.attr("xlink:href", function(d) {
return d[1]
})
.attr("width", 40)
.attr("height", 40);
g.selectAll("circle")
.data(insects[i], function(d) {
return d
})
.enter().append("circle")
.attr('cx', function(d, index) {
return x(insects[i].length) / insects[i].length * index;
})
.attr("r", 20)
.attr("cy", function(d, index) {
return y.bandwidth() * i
})
.style("fill", function(d) {
return "url(#insect" + (d[0].split(" ").join("")) + ")"
});
}
Here is your updated plunker: http://plnkr.co/edit/WLC2ihpzsjDUgcuu910O?p=preview
PS : Your code is working, but I have to say that your for loop is unnecessary (and even awkward) in a D3 dataviz. This is not the D3 way of accessing the data. Thus, I suggest you completely refactor your code in that block.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.