如何在d3.js中填充svg圆圈内的图像

How to fill an image inside my svg circles in d3.js

本文关键字:图像 svg 填充 d3 js      更新时间:2023-09-26

这是我在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')

但是,我不想在圆圈内填充绿色,而是想在json数据中url所在的每个圆圈内填充不同的图像。我一直在尝试使用.attr('fill',url(函数(d){return d.url})),但它不起作用。我是d3的新手,有人能帮我解决这个任务吗?

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

像这样:

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

假设您有一个这样的数据集:

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');

对所有数据进行迭代,并使用图像和圆进行尽可能多的def。圆圈内的填充传递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 + ")");
})

此处为工作代码

受此SO答案的启发,