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

place image inside grid using d3js

我想根据使用 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 内渲染,但未显示。

这是当前结果:

这是预期的结果:

谁能弄清楚这里的问题是什么?感谢您的帮助。

参见 here and here - meaning you can solve your issue by setting up 4 <patterns> in the <defs> for your svg and then use them as fills for each rect. There's a good d3 approach for that here

工作示例:

// 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: 
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>

也可以通过以下方式实现:

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>