使用d3js将图像放置在网格内

3
我希望使用d3.js根据数据对象在每个网格中放置图像。 在这里,使用d3js库将每个正方形渲染为网格。问题在于图像未显示在每个网格内,但在每个适当的网格内呈现正确。您可以在下面的图像中找到当前结果和预期结果。 以下是代码:

var data = [
    [{
        "x": 1,
        "y": 1,
        "width": 400,
        "height": 400,
        "image": "https://lh3.googleusercontent.com/wAPeTvxh_EwOisF8kMR2L2eOrIOzjfA5AjE28W5asyfGeH85glwrO6zyqL71dCC26R63chADTO7DLOjnqRoXXOAB8t2f4C3QnU6o0BA"
    }, {
        "x": 401,
        "y": 1,
        "width": 400,
        "height": 400,
        "image": "https://lh3.googleusercontent.com/Skyrdo9OUfXzZ-1N-jdhGbmpkx6G7r9QYfA3p6EKhb0u9ES4cZD9Z9C92BxM3A9VyLgHJHB7ALTPOlIfJxVLrpzYrLzPIUZsQX9mD4U"
    }],
    [{
        "x": 1,
        "y": 401,
        "width": 400,
        "height": 400,
        "image": "https://lh3.googleusercontent.com/0cDOOJjp8pUGDDFLqHFITEi35uMGZ5wHpZ9KTKridxk71kpR9MfeydpQqG5n8Mvetvkg5iVuZGeL2xMvxgBY_UL-T9p0x_Eo4EAh"
    }, {
        "x": 401,
        "y": 401,
        "width": 400,
        "height": 400,
        "image": "https://lh3.googleusercontent.com/IsGCHOz6W_CthCyx28PlKaZSzTHMY-nzZVBu0UUKTkhfD52WmJ-xvOIverssPjgBAGeSIBGwbP2qt7OJ-HpI7t-mToRc_xSFhCDv"
    }]
]
var grid = d3
    .select("#grid")
    .append("svg")
    .attr("width", "1350px")
    .attr("height", "1350px");

var row = grid
    .selectAll(".row")
    .data(data)
    .enter()
    .append("g")
    .attr("class", "row");

var column = row
    .selectAll(".square")
    .data(function(d) {
        return d;
    })
    .enter()
    .append("rect")
    .attr("class", "square")
    .attr("x", function(d) {
        return d.x;
    })
    .attr("y", function(d) {
        return d.y;
    })
    .attr("width", function(d) {
        return d.width;
    })
    .attr("height", function(d) {
        return d.height;
    })
    .style("fill", "#fff")
    .style("stroke", "#222")
    .attr("transform", "translate(50,50)scale(0.5)")
    .append("svg:image")
    .attr("xlink:href", function(d) {
        return d.image;
    })
    .attr("width", function(d) {
        return d.width;
    })
    .attr("height", function(d) {
        return d.height;
    });
<html>

<head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
    <div id="grid"></div>
    <script src="stack.js" type="text/javascript"></script>
</body>

</html>

图片正常渲染在rect中,但是没有显示出来。

这是当前的结果:

这是当前的结果

这是期望的结果:

这是期望的结果

有人能找出问题所在吗?任何帮助将不胜感激。


2
你正在尝试将SVG图像附加在矩形内部。这是行不通的。请将图像附加到组或SVG元素本身。 - enxaneta
2个回答

1
请参见此处此处 - 这意味着您可以通过在svg的<defs>中设置4个<patterns>,然后将它们用作每个rectfill来解决问题。这里有一个很好的d3方法 工作示例:

// your OP code for data
var data = [
  [
    {
      "x": 1, 
      "y": 1, 
      "width": 400, 
      "height": 400,  
      "image": "https://lh3.googleusercontent.com/wAPeTvxh_EwOisF8kMR2L2eOrIOzjfA5AjE28W5asyfGeH85glwrO6zyqL71dCC26R63chADTO7DLOjnqRoXXOAB8t2f4C3QnU6o0BA"
    }, 
    {
      "x": 401, 
      "y": 1, 
      "width": 400, 
      "height": 400, 
      "image": "https://lh3.googleusercontent.com/Skyrdo9OUfXzZ-1N-jdhGbmpkx6G7r9QYfA3p6EKhb0u9ES4cZD9Z9C92BxM3A9VyLgHJHB7ALTPOlIfJxVLrpzYrLzPIUZsQX9mD4U"}
  ], 
  [
    {
      "x": 1, 
      "y": 401, 
      "width": 400, 
      "height": 400, 
      "image": "https://lh3.googleusercontent.com/0cDOOJjp8pUGDDFLqHFITEi35uMGZ5wHpZ9KTKridxk71kpR9MfeydpQqG5n8Mvetvkg5iVuZGeL2xMvxgBY_UL-T9p0x_Eo4EAh"
    }, 
    {
      "x": 401, 
      "y": 401, 
      "width": 400, 
      "height": 400, 
      "image": "https://lh3.googleusercontent.com/IsGCHOz6W_CthCyx28PlKaZSzTHMY-nzZVBu0UUKTkhfD52WmJ-xvOIverssPjgBAGeSIBGwbP2qt7OJ-HpI7t-mToRc_xSFhCDv"
    }
  ]
]

// your OP code for the svg
var grid = d3
    .select("#grid")
    .append("svg")
    .attr("width", "1350px")
    .attr("height", "1350px");

// NEW code to add defs with patterns containing images
// See this post: https://stackoverflow.com/questions/41486864/svg-image-inside-rect-not-displayed?noredirect=1&lq=1
var defs = grid.append("svg:defs");

for (let r=0; r<data.length; r++) {
  for (let c=0; c<data[r].length; c++) {
    let gridItem = data[r][c];
    gridItem.imgId = `img_${r}_${c}`;
    defs.append("svg:pattern")
      .attr("id", gridItem.imgId)
      .attr("width", gridItem.width)
      .attr("height", gridItem.height)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", gridItem.image)
      .attr("width", gridItem.width)
      .attr("height", gridItem.height)
      .attr("x", 0)
      .attr("y", 0);  
  }
}

// your OP code for rows
var row = grid
  .selectAll(".row")
  .data(data)
  .enter()
  .append("g")
  .attr("class", "row");

// your adjusted OP code for columns
var column = row
  .selectAll(".square")
  .data(function(d) {return d;})
  .enter()
  .append("rect")
  .attr("class", "square")
  .attr("x", function(d) {return d.x;})
  .attr("y", function(d) {return d.y;})
  .attr("width", function(d) {return d.width;})
  .attr("height", function(d) {return d.height;})
  .style("fill", "#fff")
  .style("stroke", "#222")
  .attr("transform", "translate(50,50)scale(0.5)")
  // instead of adding svg:image use the defs instead
  .style("fill", function(d) {return "url(#" + d.imgId + ")";})
<html>

<head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
    <div id="grid"></div>
    <script src="stack.js" type="text/javascript"></script>
</body>

</html>


1
感谢您的努力。但是这些图片已经手动添加了,如果有250列和行,该怎么办? - Adharsh Chottu
1
@AdharshChottu - 请看我的编辑 - 图像现在已经添加到一个循环中,该循环识别data的行/列结构并达到相同的结果。我还从data中删除了imgId,并在处理图像时动态添加它。这样改进了答案吗? - Robin Mackenzie

0

也可以使用以下方法实现:

var data = [{
    "x": 1,
    "y": 1,
    "width": 400,
    "height": 400,
    "image": "https://lh3.googleusercontent.com/wAPeTvxh_EwOisF8kMR2L2eOrIOzjfA5AjE28W5asyfGeH85glwrO6zyqL71dCC26R63chADTO7DLOjnqRoXXOAB8t2f4C3QnU6o0BA"
}, {
    "x": 401,
    "y": 1,
    "width": 400,
    "height": 400,
"image": "https://lh3.googleusercontent.com/Skyrdo9OUfXzZ-1N-jdhGbmpkx6G7r9QYfA3p6EKhb0u9ES4cZD9Z9C92BxM3A9VyLgHJHB7ALTPOlIfJxVLrpzYrLzPIUZsQX9mD4U"
}, {
    "x": 1,
    "y": 401,
    "width": 400,
    "height": 400,
    "image": "https://lh3.googleusercontent.com/0cDOOJjp8pUGDDFLqHFITEi35uMGZ5wHpZ9KTKridxk71kpR9MfeydpQqG5n8Mvetvkg5iVuZGeL2xMvxgBY_UL-T9p0x_Eo4EAh"
}, {
    "x": 401,
    "y": 401,
    "width": 400,
    "height": 400,
    "image": "https://lh3.googleusercontent.com/IsGCHOz6W_CthCyx28PlKaZSzTHMY-nzZVBu0UUKTkhfD52WmJ-xvOIverssPjgBAGeSIBGwbP2qt7OJ-HpI7t-mToRc_xSFhCDv"
}]
var grid = d3
    .select("#grid")
    .append("svg")
    .attr("width", "1350px")
    .attr("height", "1350px");

/* var row = grid
    .selectAll(".row")
    .data(data)
    .enter()
    .append("g")
    .attr("class", "row"); */

var column = grid
    .selectAll(".square")
    .data(data)
    .enter()
    .append("rect")
    .attr("class", "square")
    .attr("x", function(d) {
        return d.x;
    })
    .attr("y", function(d) {
        return d.y;
    })
    .attr("width", function(d) {
        return d.width;
    })
    .attr("height", function(d) {
        return d.height;
    })
    .style("fill", "#fff")
    .style("stroke", "#222");

var images = grid
    .selectAll("image")
    .data(data)
    .enter()
    .append("svg:image")
    .attr("xlink:href", function(d) {
        return d.image;
    })
    .attr("width", function(d) {
        return d.width;
    })
    .attr("height", function(d) {
        return d.height;
    })
    .attr("x", function(d) {
        return d.x;
    })
    .attr("y", function(d) {
        return d.y;
    });
//remove invalid image tags
d3.selectAll("image").filter(function() {
    return d3.select(this).attr("href") == null
}).remove()
<html>

<head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
    <div id="grid"></div>
    <script src="stack.js" type="text/javascript"></script>
</body>

</html>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接