D3选择烤我的面条!
我有一系列嵌套选择,需要根据输入字段进行更新。我有4个工作中有3个。主要问题是第三个选择更新 innerSArray ,黄色条形未更新。我认为问题来自于更深层次的问题,但不确定。我不得不.merge()
以前的选择。
要更新嵌套的.append()
,我已经做了一个新的d3.selectAll()
,但是不确定这是否是正确的方法。我已经针对 innerM 和 innerSM 做到了这一点。
如何才能正确更新第三个选择?我应该把嵌套的附件拆开吗?
.outer {
border: 1px solid black;
background-color: grey;
width: 100%;
height: 100px;
position: relative;
display: flex;
}
.inner {
display: flex;
justify-content: flex-start;
border: 1px solid blue;
background-color: cyan;
height: 50px;
position: relative;
}
.innerM {
display: flex;
border: 1px solid blue;
background-color: magenta;
height: 25px;
position: relative;
}
.sr {
display: flex;
background-color: yellow;
height: 12px;
}
.sm {
display: flex;
background-color: black;
height: 6px;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>#</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
</head>
<body>
<p>Inner: <input id="increment" type="number" value="1" step="1" max="5" /></p>
<p>InnerM: <input id="incrementM" type="number" value="1" step="1" max="5" /></p>
<p>SR: <input id="incrementSR" type="number" value="1" step="1" max="5" /></p>
<p>SM: <input id="incrementSM" type="number" value="1" step="1" max="5" /></p>
<div id="anchor"></div>
<script>
const increment = document.getElementById('increment');
const incrementM = document.getElementById('incrementM');
const incrementSR = document.getElementById('incrementSR');
const incrementSM = document.getElementById('incrementSM');
const anchor = d3.select('#anchor');
const data = [
{
"outer": [
{
"inner": [
{ "r": 40,
"m": 10,
"s": []
},
{ "r": 70,
"m": 13,
"s": []
},
{ "r": 10,
"m": 15,
"s": [
{
"r": 20,
"m": 5
}
] },
{ "r": 15,
"m": 9,
"s": []
},
{ "r": 52,
"m": 20,
"s": []
},
{ "r": 96,
"m": 30,
"s": [
{
"r": 50,
"m": 10
}
] },
{ "r": 192,
"m": 60,
"s": []
},
{ "r": 301,
"m": 50,
"s": []
}
]
}
]
}
];
increment.addEventListener('change', function() {
update(data);
});
incrementM.addEventListener('change', function() {
update(data);
});
incrementSR.addEventListener('change', function() {
update(data);
});
incrementSM.addEventListener('change', function() {
update(data);
});
function update(data) {
// main data
let root = anchor.selectAll('.root').data(data);
root.exit().remove();
root = root.enter()
.append('div')
.attr('class', 'root')
.merge(root)
// outer array
let outer = root.selectAll('.outer').data(function(d) { return d.outer });
outer.exit().remove();
outer = outer.enter()
.append('div')
.attr('class','outer')
.merge(outer);
// inner array
let inner = outer.selectAll('.inner').data(function(d) { return d.inner; });
// UPDATE INNER
inner
.transition()
.duration(1000)
.style('width', function(d) { return d.r*increment.value+'px'; });
inner.exit().remove();
inner = inner.enter()
.append('div')
.attr("class", "inner")
.style('width', function(d) { return d.r+'px'; })
.append('div')
.attr("class", "innerM")
.style('width', function(d) { return d.m+'px'; })
//.merge(inner); I think there might be an issue here, removing it helps, but not a complete fix
// UPDATE INNER-M - Not sure if this is the best way to update
let innerM = d3.selectAll('.innerM')
.transition()
.duration(1000)
.style('width', function(d) { return d.m*incrementM.value+'px'; });
// Child array
let innerSArray = inner.selectAll('.innerM').data(function(d) { return d.s; })
innerSArray // This doen't get updated
.transition()
.duration(1000)
.style('width', function(d) { console.log(d.r); return d.r*incrementSR.value+'px'; });
innerSArray.exit().remove()
innerSArray = innerSArray.enter()
.append('div')
.attr('class','sr')
.style('width', function(d) { return d.r+'px'; })
.append('div')
.attr('class','sm')
.style('width', function(d) { return d.m+'px'; })
.merge(innerSArray);
// UPDATE INNER-SM - Not sure if this is the best way to update
let innerSM = d3.selectAll('.sm')
.transition()
.duration(1000)
.style('width', function(d) { return d.m*incrementSM.value+'px'; });
}
//run once
update(data);
</script>
</body>
</html>
答案 0 :(得分:0)
我设法通过将.inner
选择项上的双重追加拆分为自己的嵌套选择项来解决此问题。这需要将.innerM
的返回数据包装在数组文字中。然后,我得以继续嵌套选择。在发布此问题之前,我以前曾以这种方式进行过尝试,但是数据结构还有另一个问题。并非在每个对象中都声明了s
数组。即完全缺少s
属性,而不是一个空数组。这导致数据联接出现问题。
.outer {
border: 1px solid black;
background-color: grey;
width: 100%;
height: 100px;
position: relative;
display: flex;
}
.inner {
display: flex;
justify-content: flex-start;
border: 1px solid blue;
background-color: cyan;
height: 50px;
position: relative;
}
.innerM {
display: flex;
border: 1px solid blue;
background-color: magenta;
height: 25px;
position: relative;
}
.sr {
display: flex;
background-color: yellow;
height: 12px;
}
.sm {
display: flex;
background-color: black;
height: 6px;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>#</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
</head>
<body>
<p>Inner: <input id="increment" type="number" value="1" step="1" max="5" /></p>
<p>InnerM: <input id="incrementM" type="number" value="1" step="1" max="5" /></p>
<p>SR: <input id="incrementSR" type="number" value="1" step="1" max="5" /></p>
<p>SM: <input id="incrementSM" type="number" value="1" step="1" max="5" /></p>
<div id="anchor"></div>
<script>
const anchor = d3.select('#anchor');
const increment = document.getElementById('increment');
const incrementM = document.getElementById('incrementM');
const incrementSR = document.getElementById('incrementSR');
const incrementSM = document.getElementById('incrementSM');
const data = [
{
"outer": [
{
"inner": [
{ "r": 40,
"m": 10,
"s": []
},
{ "r": 70,
"m": 13,
"s": []
},
{ "r": 10,
"m": 15,
"s": [
{
"r": 20,
"m": 5
}
] },
{ "r": 15,
"m": 9,
"s": []
},
{ "r": 52,
"m": 20,
"s": []
},
{ "r": 96,
"m": 30,
"s": [
{
"r": 50,
"m": 10
}
] },
{ "r": 192,
"m": 60,
"s": []
},
{ "r": 301,
"m": 50,
"s": []
}
]
}
]
}
];
increment.addEventListener('change', function() {
update(data);
});
incrementM.addEventListener('change', function() {
update(data);
});
incrementSR.addEventListener('change', function() {
update(data);
});
incrementSM.addEventListener('change', function() {
update(data);
});
function update(data) {
// main data
let root = anchor.selectAll('.root').data(data);
root.exit().remove();
root = root.enter()
.append('div')
.attr('class', 'root')
.merge(root)
// outer array
let outer = root.selectAll('.outer').data(function(d) { return d.outer });
outer.exit().remove();
outer = outer.enter()
.append('div')
.attr('class','outer')
.merge(outer);
let inner = outer.selectAll('.inner').data(function(d) { return d.inner; });
inner
.transition()
.duration(1000)
.style('background-color','green')
.style('width', function(d) { return d.r*increment.value+'px'; });
inner.exit().remove();
inner = inner.enter()
.append('div')
.attr("class", "inner")
.style('width', function(d) { return d.r+'px'; })
.merge(inner);
let innerM = inner.selectAll('.innerM').data(function(d) { return [d]; });
innerM
.transition()
.duration(1000)
.style('width', function(d) { return d.m*incrementM.value+'px'; });
innerM.exit().remove();
innerM = innerM.enter()
.append('div')
.attr("class", "innerM")
.style('width', function(d) { return d.m+'px'; })
.merge(innerM)
let sr = innerM.selectAll('.sr').data(function(d) { return d.s; });
sr
.transition()
.duration(1000)
.style('width', function(d) { return d.r*incrementSR.value+'px'; });
sr.exit().remove();
sr = sr.enter()
.append('div')
.attr("class", "sr")
.style('width', function(d) { return d.r+'px'; })
.merge(sr)
let sm = sr.selectAll('.sm').data(function(d) { return [d]; });
sm
.transition()
.duration(1000)
.style('width', function(d) { return d.m*incrementSM.value+'px'; });
sm.exit().remove();
sm = sm.enter()
.append('div')
.attr("class", "sm")
.style('width', function(d) { return d.m+'px'; })
}
//run once
update(data);
</script>
</body>
</html>