Похоже, когда я использую функцию «вставить», новый элемент всегда вставляется как дочерний, а не как родственный.
Я до сих пор не понимаю, почему это так, поскольку функция вставки должна фактически вставлять новый элемент перед указанным элементом, а не в указанный элемент как дочерний.
В основном я пытаюсь создать элемент «прямоугольник» рядом с элементами «текст».
Цель состоит в том, чтобы поместить цвет фона позади моих текстов в моей диаграмме Санки d3.
// NODE TEXT
this.nodes
.selectAll('text')
.data(this.data.nodes)
.join(
(enter) =>
enter
.append('text')
.text((d) => `${d.name + ': ' + d.value}`)
.style('fill', '#000000')
.attr('text-anchor', 'right')
.attr('x', (d, i) => {
return d.x0 + (d.x1 - d.x0) / 0.5;
})
.attr('y', (d, i) => {
return d.y0 + (d.y1 - d.y0) / 2;
})
.attr('dy', '0.35em')
.attr('transform', (d, i) => {
const x = d.x0 + (d.x1 - d.x0) / 2;
const y = d.y0 + (d.y1 - d.y0) / 2;
return `rotate(0, ${x}, ${y})`;
})
.call(getTextBox)
.insert('rect', 'text')
.attr('width', function (d) {
return d.bbox.width;
})
.attr('height', function (d) {
return d.bbox.height;
})
.attr('x', function (d) {
return d.bbox.x;
})
.attr('y', function (d) {
return d.bbox.y;
})
.style('fill', 'grey'),
(update) =>
update
.transition()
.duration(1000)
.ease(d3_easeQuadInOut)
.attr('x', (d, i) => {
return d.x0 + (d.x1 - d.x0) / 2;
})
.attr('y', (d, i) => {
return d.y0 + (d.y1 - d.y0) / 2;
})
.attr('transform', (d, i) => {
const x = d.x0 + (d.x1 - d.x0) / 2;
const y = d.y0 + (d.y1 - d.y0) / 2;
return `rotate(0, ${x}, ${y})`;
})
);
function getTextBox(selection) {
selection.each(function (d) {
d.bbox = this.getBBox();
});
}
Вот изображение отображаемых HTML-элементов из моего браузера.
Обратите внимание, что элемент «rect» является дочерним по отношению к тексту, а не родственным, как хотелось бы.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Перебирать данные и привязывать текст/прямоугольник в родительской оболочке
Надеюсь, это поможет: ссылка
Результат в коде, который у вас есть, ожидаемый: это происходит потому, что insert вызывается для выделения текстов, которые действуют как родитель.
Первое, простое решение — разорвать цепочку, поэтому у вас есть selection.append и selection.insert. Например:
const svg = d3.select("svg"),
data = d3.range(5).map(e => ({
value: e
}));
svg.selectAll(null)
.data(data)
.join(enter => {
enter.append("text")
.attr("x", 20)
.attr("y", d => 20 + 30 * d.value)
.text(d => `text #${d.value}`)
.call(getTextBox);
enter.insert("rect", "text")
.attr('width', d => d.bbox.width)
.attr('height', d => d.bbox.height)
.attr('x', d => d.bbox.x)
.attr('y', d => d.bbox.y)
.style('fill', 'grey')
})
function getTextBox(selection) {
selection.each(function(d) {
d.bbox = this.getBBox();
});
}<script src = "https://d3js.org/d3.v7.min.js"></script>
<svg></svg>Однако этот SVG будет иметь следующую структуру:
<rect></rect>
<rect></rect>
<rect></rect>
...
<text></text>
<text></text>
<text></text>
...
Тем не менее, если вместо этого вам нужна следующая структура...
<rect></rect>
<text></text>
<rect></rect>
<text></text>
<rect></rect>
<text></text>
...
... вам нужно немного больше проработки insert. В этом примере я получаю соответствующие текстовые элементы по их идентификаторам:
const svg = d3.select("svg"),
data = d3.range(5).map(e => ({
value: e
}));
svg.selectAll(null)
.data(data)
.join(enter => {
enter.append("text")
.attr("id", d => `text${d.value}`)
.attr("x", 20)
.attr("y", d => 20 + 30 * d.value)
.text(d => `text #${d.value}`)
.call(getTextBox);
enter.insert("rect", d => d3.select(`#text${d.value}`).node())
.attr('width', d => d.bbox.width)
.attr('height', d => d.bbox.height)
.attr('x', d => d.bbox.x)
.attr('y', d => d.bbox.y)
.style('fill', 'grey')
})
function getTextBox(selection) {
selection.each(function(d) {
d.bbox = this.getBBox();
});
}<script src = "https://d3js.org/d3.v7.min.js"></script>
<svg></svg>Большое спасибо! Это точно решение!
Спасибо за ваш ответ. К сожалению, пример не помогает, потому что мне сначала нужны текстовые элементы, чтобы получить значения (x, y, ширина, высота) для новых прямоугольных элементов. Прямоугольники должны отображаться непосредственно за текстами. Поэтому мне нужно сначала прочитать их.