#javascript #d3.js
#javascript #d3.js
Вопрос:
Я пытаюсь удалить элементы rect из svg, присоединив пустой массив к выделенному d3.
Это не работает.
Предположительно, я что-то неправильно понял.
Приведенный ниже фрагмент кода настраивает svg. Когда вы нажимаете кнопку «Очистить», ничего не происходит.
У меня есть 3 вопроса (также отмеченные в комментариях к коду) ;
- Почему выделение не сообщает размер 4 после объединения 4 элементов данных и создания 4 связанных элементов?
- Почему в функции clearSVG размер exit() равен 0 после присоединения данных «no» к существующему выделению.
- Почему прямоугольники не удалены (вероятно, ответ дан в Q2).
function init(){
let initialData = [
{x:0,y:0,c:"black"},
{x:0,y:90,c:"orange"},
{x:90,y:0,c:"green"},
{x:90,y:90,c:"yellow"}
];
let nodes = d3.select("#svg").selectAll("dataNode") ;
//console.log(`empty nodes size: ${nodes.size()} all good .. ?`); // reports 0
nodes
.data(initialData)
.enter()
.append(`svg:rect`)
.attr("class", `dataNode`)
.attr("x", function(d){return d.x;})
.attr("y", function(d){return d.y;})
.attr("width", 10)
.attr("height", 10)
.attr("fill", function(d){return d.c;}) ;
//console.log(`initial data nodes size: ${nodes.size()} - Q1. why is this not 4 ?`); //reports 0
};
function clearSVG(){
let nodes = d3.select("#svg").selectAll(".dataNode"); // all 4 rect elements in the svg
//console.log(`nodes size: ${nodes.size()}`);// looking good.. 4 nodes reported
let newData = [] ; // nada, no data
nodes.data(newData) ; // join nothing to the rects - no datum for any element in the selection
//console.log(`exit size: ${nodes.exit().size()} - Q2. Why is this 0 and not 4 ?`);
nodes.exit().remove();
//console.log(`Q3. Why are the rects still present ?`);
};
init();
*{
border:none;
padding:0;
font-family:Arial;
box-sizing:border-box;
}
body{
margin:10px;
}
#svg{
display: inline-block ;
width:100px;
height:100px;
}
#plotBackGround{
fill: #FBFBFB;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="svg" viewBox="0 0 100 100" >
<rect id="plotBackGround" x="0" y="0" width="100" height="100"></rect>
</svg>
<BR><BR>
<button class="btn btn-primary" onclick="clearSVG();">Clear</button>
Редактировать
Подводя итог сути принятого ответа; selection.data(), .enter(), .append(), .exit() и .remove() возвращают новые выборки. Они не изменяют выделение, для которого они вызываются, или возвращают ссылку на него или его части.
Завершить редактирование
Ответ №1:
Проблема
Проблема здесь довольно проста: у вас нет правильного выбора обновления.
Давайте посмотрим. Сначала вы делаете это:
let nodes = d3.select("#svg").selectAll(".dataNode");
Затем вы изменяете данные:
let newData = [];
nodes.data(newData);
Однако вы не меняете nodes
, которые остаются такими, какими они были. Когда вы позже сделаете:
nodes.exit().remove();
На самом деле вы просто делаете это:
d3.select("#svg").selectAll(".dataNode").exit().remove();
Что, как вы можете видеть, имеет мало смысла.
Решение
Напишите правильный выбор обновления. Это должно быть:
nodes = nodes.data(newData);
Которое, если мы подставим значение nodes
, даст нам фактически это:
d3.select("#svg").selectAll(".dataNode").data(newData).exit().remove();
Вот код только с этим изменением:
function init(){
let initialData = [
{x:0,y:0,c:"black"},
{x:0,y:90,c:"orange"},
{x:90,y:0,c:"green"},
{x:90,y:90,c:"yellow"}
];
let nodes = d3.select("#svg").selectAll("dataNode") ;
//console.log(`empty nodes size: ${nodes.size()} all good .. ?`); // reports 0
nodes
.data(initialData)
.enter()
.append(`svg:rect`)
.attr("class", `dataNode`)
.attr("x", function(d){return d.x;})
.attr("y", function(d){return d.y;})
.attr("width", 10)
.attr("height", 10)
.attr("fill", function(d){return d.c;}) ;
//console.log(`initial data nodes size: ${nodes.size()} - Q1. why is this not 4 ?`); //reports 0
};
function clearSVG(){
let nodes = d3.select("#svg").selectAll(".dataNode"); // all 4 rect elements in the svg
//console.log(`nodes size: ${nodes.size()}`);// looking good.. 4 nodes reported
let newData = [] ; // nada, no data
nodes = nodes.data(newData) ; // join nothing to the rects - no datum for any element in the selection
//console.log(`exit size: ${nodes.exit().size()} - Q2. Why is this 0 and not 4 ?`);
nodes.exit().remove();
//console.log(`Q3. Why are the rects still present ?`);
};
init();
*{
border:none;
padding:0;
font-family:Arial;
box-sizing:border-box;
}
body{
margin:10px;
}
#svg{
display: inline-block ;
width:100px;
height:100px;
}
#plotBackGround{
fill: #FBFBFB;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="svg" viewBox="0 0 100 100" >
<rect id="plotBackGround" x="0" y="0" width="100" height="100"></rect>
</svg>
<BR><BR>
<button class="btn btn-primary" onclick="clearSVG();">Clear</button>
Комментарии:
1. это, кстати, также причина того, почему
console.log
выводится 0 (его первый вопрос)2. @JanWendland Да, три вопроса в списке OP на самом деле являются всего лишь одной проблемой.
3. @Bob Да, я удалил этот пример, поскольку я не пояснил, какие методы вносят изменения на месте.