23

My goal is to add an image into an existing circle with d3. The circle will render and is interactive with mouseover method, but only when I use "fill", "color", and not something more sophisticated like .append("image").

g.append("circle")
    .attr("class", "logo")
    .attr("cx", 700)
    .attr("cy", 300)
    .attr("r", 10)
    .attr("fill", "black")       // this code works OK
    .attr("stroke", "white")     // displays small black dot
    .attr("stroke-width", 0.25)
    .on("mouseover", function(){ // when I use .style("fill", "red") here, it works 
        d3.select(this)        
            .append("svg:image")
            .attr("xlink:href", "/assets/images/logo.jpeg")
            .attr("cx", 700)
            .attr("cy", 300)
            .attr("height", 10)
            .attr("width", 10);
     });

The image doesn't show after I mouse over. Using Ruby on Rails app, where my image "logo.jpeg" is stored in the assets/images/ directory. Any help for getting my logo to show within the circle? Thanks.

qtmfld
  • 2,916
  • 2
  • 21
  • 36
DeBraid
  • 8,751
  • 5
  • 32
  • 43
  • 2
    Try setting the image as a [pattern](http://stackoverflow.com/questions/3796025/fill-svg-path-element-with-a-background-image). – Lars Kotthoff Oct 05 '13 at 21:21

2 Answers2

31

As Lars says you need to use pattern, once you do that it becomes pretty straightforward. Here's a link to a conversation in d3 google groups about this. I've set up a fiddle here using the image of a pint from that conversation and your code above.

To set up the pattern:

    <svg id="mySvg" width="80" height="80">
      <defs id="mdef">
        <pattern id="image" x="0" y="0" height="40" width="40">
          <image x="0" y="0" width="40" height="40" xlink:href="http://www.e-pint.com/epint.jpg"></image>
        </pattern>
      </defs>
    </svg>

Then the d3 where we only change the fill:

svg.append("circle")
         .attr("class", "logo")
         .attr("cx", 225)
         .attr("cy", 225)
         .attr("r", 20)
         .style("fill", "transparent")       
         .style("stroke", "black")     
         .style("stroke-width", 0.25)
         .on("mouseover", function(){ 
               d3.select(this)
                   .style("fill", "url(#image)");
         })
          .on("mouseout", function(){ 
               d3.select(this)
                   .style("fill", "transparent");
         });
Dendi Handian
  • 348
  • 2
  • 12
user1614080
  • 2,854
  • 1
  • 19
  • 22
  • Brilliant, thank you. The above worked perfectly, although I am not familiar with defs or pattern, so this was new learning. To centre the image ensure width & height as same # of pixels as circle DIAMETER (in this case r= 10, h, w = 20). – DeBraid Oct 06 '13 at 16:47
  • 1
    I saw your fiddle. But the question is how I can load in each circle and specific image? @user1614080 – RezKesh May 22 '15 at 15:15
  • how to remove mouseover function here – srinivas gowda Aug 30 '17 at 11:06
1
nodeEnter.append("svg:image")
            .attr('x',-9)
            .attr('y',-12)
            .attr('width', 20)
            .attr('height', 24)
            .attr("xlink:href", function(d) { 
         if(d.type=="root"){
            return "resources/images/test.png";}
            else if(d.type.toLowerCase()=="A"){
                return "resources/icon01/test1.png";}
            else if(d.type=="B"){
                return "resources/icon01/test2.png";}
            })
            .append("svg:title")
              .text(function(d){
              if(d.type=="root"){
                return "Root Name:"+d.name;}
              else if(d.type=="test"){
                return "Name:"+d.name;}
            });
Aravind Cheekkallur
  • 3,157
  • 6
  • 27
  • 41
  • I tried to implement this mixed success. The img was loaded into the DOM, but I could not get it to render within the circle. Is this common, or are you aware of a work around to this? I resorted to the slightly more involved method above and est. a pattern. – DeBraid Jun 02 '14 at 13:54
  • @DeBraid may i know which d3 graph you are using? if it was the problem of rendering please check with firefox browser. \ – Aravind Cheekkallur Jun 03 '14 at 04:28