Добавить изображение в виде фрагментов в D3.js Сетка

#javascript #html #d3.js #visualization

#javascript #HTML #d3.js #визуализация

Вопрос:

Я пытаюсь добавить изображение в d3.js элемент svg по частям, чтобы составить сетку размером 12×12. У меня есть сетка 12×12, но я могу только понять, как загрузить все изображение в каждый раздел сетки, а не добавлять изображение по частям, чтобы создать одно плиточное изображение в конце. Любые мысли о том, как это можно решить, будут оценены, спасибо.

Примечание: данные в файле csv — это просто координаты, которые составляют сетку 12×12.

 var data = d3.range(36).map(function(i) {
  return {
    x_coordinate: (i % 6) * 12,
    y_coordinate: Math.floor(i / 6) * 12,
  };
});
// set the dimensions and margins of the graph
var margin = {
    top: 1,
    bottom: 15,
    left: 0,
    right: 0
  },
  width = 350,
  height = 350;

// append the svg object to the body of the page
var svg = d3.select("#tile_photo")
  .append("svg")
  .attr("width", width   margin.left)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform",
    "translate("   margin.left   ","   margin.top   ")");

// Labels of row and columns -> unique identifier of the column called 'xCoordinate' and 'yCoordinate'
var xCoordinate = d3.map(data, function(d) {
    return d.x_coordinate;
  }).keys(),
  yCoordinate = d3.map(data, function(d) {
    return d.y_coordinate;
  }).keys();

// Build X and Y scales and axis:
var x = d3.scaleBand()
  .range([0, width])
  .domain(xCoordinate)
  .padding(0.025),
  y = d3.scaleBand()
  .range([0, height])
  .domain(yCoordinate)
  .padding(0.025);

// adding the 12x12 rects that will make up the tile photo
var tileImage = svg.selectAll()
  .data(data, function(d) {
    return d.x_coordinate   ':'   d.y_coordinate;
  })
  .enter();

tileImage.append("svg:image")
  .attr("x", function(d) {
    return x(d.x_coordinate)
  })
  .attr("y", function(d) {
    return y(d.y_coordinate)
  })
  .attr("rx", 0)
  .attr("ry", 0)
  .attr("width", x.bandwidth())
  .attr("height", y.bandwidth())
  .attr("xlink:href", "https://via.placeholder.com/72");  
 <script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Create a div where the graph will take place -->
<div id="tile_photo" align="center"></div>  

Ответ №1:

Если вас интересует только визуальная часть, вы можете сделать это, добавив изображение только один раз и используя clipPath . Это создает фильтр, который накладывается на изображение и позволяет отображать только пиксели в определенных местах.

Я не уверен, позволит ли это вам обнаруживать клики по отдельным плиткам. Если вы этого хотите, я действительно рекомендую использовать сервер для нарезки и подачи изображения в виде плиток для вас.

 var data = d3.range(36).map(function(i) {
  return {
    x_coordinate: (i % 6) * 12,
    y_coordinate: Math.floor(i / 6) * 12,
  };
});
// set the dimensions and margins of the graph
var margin = {
    top: 1,
    bottom: 15,
    left: 0,
    right: 0
  },
  width = 350,
  height = 350;

// append the svg object to the body of the page
var svg = d3.select("#tile_photo")
  .append("svg")
  .attr("width", width   margin.left)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform",
    "translate("   margin.left   ","   margin.top   ")");

// Labels of row and columns -> unique identifier of the column called 'xCoordinate' and 'yCoordinate'
var xCoordinate = d3.map(data, function(d) {
    return d.x_coordinate;
  }).keys(),
  yCoordinate = d3.map(data, function(d) {
    return d.y_coordinate;
  }).keys();

// Build X and Y scales and axis:
var x = d3.scaleBand()
  .range([0, width])
  .domain(xCoordinate)
  .padding(0.025),
  y = d3.scaleBand()
  .range([0, height])
  .domain(yCoordinate)
  .padding(0.025);

var clipPath = svg
  .append("clipPath")
  .attr("id", "crop")
  .selectAll("rect")
  .data(data, function(d) {
    return d.x_coordinate   ':'   d.y_coordinate;
  })
  .enter()
  .append("svg:rect")
  .attr("width", x.bandwidth())
  .attr("height", y.bandwidth())
  .attr("x", function(d) {
    return x(d.x_coordinate)
  })
  .attr("y", function(d) {
    return y(d.y_coordinate)
  });

var tileImage = svg.append("svg:image")
  .attr("width", width)
  .attr("height", height)
  .attr("clip-path", "url(#crop)")
  .attr("xlink:href", "https://via.placeholder.com/72");  
 <script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Create a div where the graph will take place -->
<div id="tile_photo" align="center"></div>