Мне нужно расположить несколько SVG-фигур на основе регулярной двумерной сетки, которая определяется следующим образом:
data = [[0, 0], [0, 1], [0, 2], ...]
Существует одна фигура на элемент data
. Его фактическое положение является функцией соответствующей координаты сетки. Кроме того, я должен разместить несколько текстовых меток на каждой сетке и применить масштабирование и панорамирование на основе D3.js.
Часть кода JS выглядит следующим образом, а работает как ожидалось .
gap = 10;
size = 40;
data = [[0, 0], [0, 1], [0, 2]];
var gs = d3.select("svg").selectAll("g").data(data).enter().append("g");
var boxes = d3.selectAll("g").append("rect")
.attr("width", size)
.attr("height", size)
.attr("x", d => d[0]*(size+gap))
.attr("y", d => d[1]*(size+gap));
var text = d3.selectAll("g").append("text")
.attr("x", d => d[0]*(size+gap)+2)
.attr("y", d => d[1]*(size+gap)+size/2)
.text((d, i) => i);
var zoom = d3.zoom()
.extent([[0, 0], [300, 400]])
.scaleExtent([1, 20])
.on("zoom", zoomBoxes);
d3.select("svg").call(zoom)
function zoomBoxes() {
d3.selectAll("g").attr("transform", d3.event.transform);
}
Также вы можете видеть, мне нужно пересчитать атрибуты x
и y
для каждой текстовой метки (только один в этом примере для простоты) и фактически записать вычисление. Определение функции для вычисления упростит дело, так как это сохранит только несколько символов оператора. Итак, я пришел к следующей идее: не устанавливайте положение ящиков, а используйте перевод, чтобы поместить родительские элементы g
в правильные места. Таким образом, мне нужно было бы написать код для позиционирования только один раз, и позиции текста были легко вычислены из нового источника:
gap = 10;
size = 40;
data = [[0, 0], [0, 1], [0, 2]];
var gs = d3.select("svg").selectAll("g").data(data).enter().append("g")
.attr("transform", d => "translate("+ d[0]*(size+gap) + ","
+ d[1]*(size+gap) + ")");
var boxes = d3.selectAll("g").append("rect")
.attr("width", size)
.attr("height", size)
var text = d3.selectAll("g").append("text")
.attr("x", 2)
.attr("y", size/2)
.text((d, i) => i);
var zoom = d3.zoom()
.extent([[0, 0], [300, 400]])
.scaleExtent([1, 20])
.on("zoom", zoomBoxes);
d3.select("svg").call(zoom)
function zoomBoxes() {
d3.selectAll("g").attr("transform", d3.event.transform);
}
Однако D3.js-zoom, кажется, полагается на форму x
и y
атрибутов, так что каждая фигура в предыдущем примере сбрасывается в исходную точку SVG, когда вызывается функция масштабирования. Проверьте скрипку .
Короче говоря, есть ли способ основать D3.js-zoom на относительных позициях, на которых фигуры располагаются после первоначального перевода?