如何在d3.js中填写我的svg圈内的图像

时间:2016-05-08 13:20:27

标签: javascript d3.js svg

这是我在svg中填充圈子的代码。

   var svgContainer = d3.select("body").append("svg")
                                 .attr("width", 1000)
                             .attr("height", 1000);
    var circles = svgContainer.selectAll("circle")
                      .data(nodes)
                      .enter()
                      .append("circle");

     var circleAttributes = circles
                   .attr("cx", function (d) { return d.x_axis; })
                   .attr("cy", function (d) { return d.y_axis; })
                   .attr("r", function (d) { return d.radius; })
                   .attr('fill', 'green')

但是我不想在我的圈子里填充绿色,而是想在每个圈子里面填充不同的图像,其中url在我的json数据中。我一直试图使用.attr(' fill',url(function(d){return d.url}))但它不起作用。我是d3的新手,任何人都可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

想象一下,你有一个像这样的数据集:

data = [{
  posx: 100,
  posy: 100,
  img: "https://cdn0.iconfinder.com/data/icons/flat-round-system/512/android-128.png",

}, {
  posx: 200,
  posy: 200,

  img: "https://cdn1.iconfinder.com/data/icons/social-media-set/24/Reverbnation-128.png"
}, {
  posx: 300,
  posy: 300,

  img: "https://cdn1.iconfinder.com/data/icons/user-pictures/100/male3-128.png"
}]

在svg中像这样制作defs:

var defs = svg.append('svg:defs');

迭代所有数据并使用图像和圆圈进行尽可能多的defs。 内圈的填充会传递def的ID,如.style("fill", "url(#grump_avatar" + i + ")");

data.forEach(function(d, i) {
  defs.append("svg:pattern")
    .attr("id", "grump_avatar" + i)
    .attr("width", config.avatar_size) 
    .attr("height", config.avatar_size)
    .attr("patternUnits", "userSpaceOnUse")
    .append("svg:image")
    .attr("xlink:href", d.img)
    .attr("width", config.avatar_size)
    .attr("height", config.avatar_size)
    .attr("x", 0)
    .attr("y", 0);

  var circle = svg.append("circle")
    .attr("transform", "translate(" + d.posx + "," + d.posy + ")")
    .attr("cx", config.avatar_size / 2)
    .attr("cy", config.avatar_size / 2)
    .attr("r", config.avatar_size / 2)
    .style("fill", "#fff")
    .style("fill", "url(#grump_avatar" + i + ")");

})

工作代码here

灵感来自SO answer

答案 1 :(得分:2)

从图像创建模式使用太多内存并使用多个图像会产生严重的性能问题。所以为了避免这种情况,我们可以在图像上使用剪辑路径。

像这样:

var config = {
  "avatar_size": 100
}

var body = d3.select("body");
var svg = body.append("svg")
  .attr("width", 500)
  .attr("height", 500);

var defs = svg.append('svg:defs');

data = [{
  posx: 100,
  posy: 100,
  img: "https://cdn4.iconfinder.com/data/icons/seo-and-data/500/pencil-gear-128.png",
}, {
  posx: 200,
  posy: 200,
  img: "https://cdn4.iconfinder.com/data/icons/seo-and-data/500/gear-clock-128.png"
}, {
  posx: 300,
  posy: 300,
  img: "https://cdn4.iconfinder.com/data/icons/seo-and-data/500/magnifier-data-128.png"
}];


svg .append('clipPath')
   .attr('id','clipObj')  
        .append('circle')
         .attr('cx',config.avatar_size/2)
          .attr('cy',config.avatar_size/2)
         .attr('r',config.avatar_size/2);

data.forEach(function(d,i){
  svg.append('image')
     .attr('xlink:href',d.img)
     .attr('width',config.avatar_size)
     .attr('height',config.avatar_size)
 .attr('transform','translate('+parseInt(d.posx+config.avatar_size/2)+','+parseInt(d.posy+config.avatar_size/2)+')')
     .attr('clip-path','url(#clipObj)');
});

我们也可以根据需要轻松更换剪裁区域。 以下是代码笔的链接:http://codepen.io/anon/pen/VagxKp?editors=0010