Jquery d3.js节点未正确退出
这就来了。我花了相当长的时间在这一点上-我真的很累-所以希望一些愚蠢的东西没有逃避我 我正在使用数据集在图表中创建几行。之后,使用图例,我想在更改数据集的同时隐藏线-因此更改不透明度不会剪切它 我遵循在数据集中的每个对象上添加一个启用键的路径,并将其设置为false,以便能够筛选要隐藏的对象。但是,由于我无法正确地退出()行,因此它没有按预期工作。完全删除行并再次绑定数据集可以完成任务,但会弄乱行颜色到图例项的映射 问题出在函数的某个地方 希望有人能解决这个噩梦Jquery d3.js节点未正确退出,jquery,d3.js,dataset,Jquery,D3.js,Dataset,这就来了。我花了相当长的时间在这一点上-我真的很累-所以希望一些愚蠢的东西没有逃避我 我正在使用数据集在图表中创建几行。之后,使用图例,我想在更改数据集的同时隐藏线-因此更改不透明度不会剪切它 我遵循在数据集中的每个对象上添加一个启用键的路径,并将其设置为false,以便能够筛选要隐藏的对象。但是,由于我无法正确地退出()行,因此它没有按预期工作。完全删除行并再次绑定数据集可以完成任务,但会弄乱行颜色到图例项的映射 问题出在函数的某个地方 希望有人能解决这个噩梦 我创造了一把小提琴我理解你的感
我创造了一把小提琴我理解你的感受。。。我希望这个答案能对你有所帮助 您的代码中有一些问题,因此我修复了主要问题,并在过程中添加了注释。 请记住,在我的版本中仍然有很多地方可以改进,这取决于您如何改进 我将用一些注释来更新答案,详细说明我对如何处理这段代码的想法,并在这里链接到一篇有用的文章或答案 同时检查此项和下面的代码
// .. code above is unchanged
line = d3.line()
.x(function(d) {
return x(d.date);
}).y(function(d) {
return y(d.value);
});
// notice I deleted the part where you created the groups and the path the first time
// You don't need it anymore
var legendItem = d3.select(".legend")
.selectAll("li")
.data(dataGroup)
.enter()
.append("li")
.on('click', function(d) {
if (d.enabled) {
d.enabled = false;
} else {
d.enabled = true;
}
redraw();
});
legendItem
.append("span")
.attr("class","color-square")
.style("background", function(d, i) {
// This is basically a hack for this demo
// You should find a better way to assign an index to a color
var idx = +d.key.slice(-1);
return colorScale(idx - 1);
});
legendItem
.append("span")
.text(function(d) {
return (d.values[0].name)
});
redraw = function() {
y.domain([
d3.min(dataGroup, function(c) {
return d3.min(c.values, function(d) {
return d.value;
});
}),
// In the demo I don't rescale after the datasets change, so no need to filter
// by enabled sets. If you want the max to be calculated only for enabled items
// you will also have to redraw the axis, otherwise you will display incorrect data.
d3.max(dataGroup, function(c) {
return d3.max(c.values, function(d) {
return d.value;
});
})
]);
// Notice that i filter the data passed to the .data() function,
// not after it.
lines = svg.selectAll("g.d3-group")
.data(dataGroup.filter(d => d.enabled))
// This is the Enter + update selection
var linesEnter = lines
.enter()
.append("g")
.merge(lines)
.attr("class", "d3-group")
// We want the data to go from the <g> to its child, the <path> element
// To do so, we need to rebind the data.
var pathJoin = linesEnter
.selectAll('path')
.data(d => [d]) // <= this is very important
// Enter the path and update it
var pathEnter = pathJoin
.enter()
.append("path")
.attr("class", "d3-line")
.merge(pathJoin)
.attr('d', function(d) {
return line(d.values);
})
// Notice how "i" is not used. If you log it you will see it is always 0
// as it is always the first child of its parent, the <g class="group">
.style("stroke", function(d, i) {
var idx = +d.key.slice(-1);
return colorScale(idx - 1);
});
lines.exit().remove();
}
redraw();
正确处理的一件重要事情是将数据从父级(
)传输到子级(
)。这里发生了这样的事情:
linesEnter
.selectAll('path')
.data(d => [d]) // <= here
linesEnter
.selectAll('路径')
.data(d=>[d])/我理解你的感受。。。我希望这个答案能对你有所帮助
您的代码中有一些问题,因此我修复了主要问题,并在过程中添加了注释。
请记住,在我的版本中仍然有很多地方可以改进,这取决于您如何改进
我将用一些注释来更新答案,详细说明我对如何处理这段代码的想法,并在这里链接到一篇有用的文章或答案
同时检查此项和下面的代码
// .. code above is unchanged
line = d3.line()
.x(function(d) {
return x(d.date);
}).y(function(d) {
return y(d.value);
});
// notice I deleted the part where you created the groups and the path the first time
// You don't need it anymore
var legendItem = d3.select(".legend")
.selectAll("li")
.data(dataGroup)
.enter()
.append("li")
.on('click', function(d) {
if (d.enabled) {
d.enabled = false;
} else {
d.enabled = true;
}
redraw();
});
legendItem
.append("span")
.attr("class","color-square")
.style("background", function(d, i) {
// This is basically a hack for this demo
// You should find a better way to assign an index to a color
var idx = +d.key.slice(-1);
return colorScale(idx - 1);
});
legendItem
.append("span")
.text(function(d) {
return (d.values[0].name)
});
redraw = function() {
y.domain([
d3.min(dataGroup, function(c) {
return d3.min(c.values, function(d) {
return d.value;
});
}),
// In the demo I don't rescale after the datasets change, so no need to filter
// by enabled sets. If you want the max to be calculated only for enabled items
// you will also have to redraw the axis, otherwise you will display incorrect data.
d3.max(dataGroup, function(c) {
return d3.max(c.values, function(d) {
return d.value;
});
})
]);
// Notice that i filter the data passed to the .data() function,
// not after it.
lines = svg.selectAll("g.d3-group")
.data(dataGroup.filter(d => d.enabled))
// This is the Enter + update selection
var linesEnter = lines
.enter()
.append("g")
.merge(lines)
.attr("class", "d3-group")
// We want the data to go from the <g> to its child, the <path> element
// To do so, we need to rebind the data.
var pathJoin = linesEnter
.selectAll('path')
.data(d => [d]) // <= this is very important
// Enter the path and update it
var pathEnter = pathJoin
.enter()
.append("path")
.attr("class", "d3-line")
.merge(pathJoin)
.attr('d', function(d) {
return line(d.values);
})
// Notice how "i" is not used. If you log it you will see it is always 0
// as it is always the first child of its parent, the <g class="group">
.style("stroke", function(d, i) {
var idx = +d.key.slice(-1);
return colorScale(idx - 1);
});
lines.exit().remove();
}
redraw();
正确处理的一件重要事情是将数据从父级(
)传输到子级(
)。这里发生了这样的事情:
linesEnter
.selectAll('path')
.data(d => [d]) // <= here
linesEnter
.selectAll('路径')
.data(d=>[d])/以下是使用以下修复程序重构的代码:
将初始绘制和重绘浓缩为单个函数
在这个单一功能中正确处理了输入、更新和退出模式
用于修复数据绑定(保持数据的唯一性)
对颜色使用d.key
,而不是索引(以修复漫游颜色)
修复了一些常见的代码质量问题(缺少var关键字、根据选择而不是数据进行筛选等)
我没有使用不透明度来“切换”线条,尽管这样也可以
.折线图{
宽度:800px;
高度:200px;
}
.d3轴{
字体系列:“Arial”,无衬线;
字体大小:10px;
}
.d3线{
填充:无;
笔画宽度:2px;
}
.d3轴路径{
填充:无;
冲程:#e6;
形状渲染:边缘清晰;
不透明度:0;//删除轴
}
.d3轴线{
填充:无;
冲程:#eee;
形状渲染:边缘清晰;
}
ulli{
显示:内联块;
左边距:10px;
}
.彩色广场{
显示:块;
浮动:左;
右边距:3倍;
宽度:20px;
高度:20px;
边框:1px实心#000;
}
风险值数据=[{
“名称”:“第1行”,
“日期”:“2016-10-07T23:59:07Z”,
“价值”:67
}, {
“名称”:“第1行”,
“日期”:“2016-10-15T11:35:32Z”,
“价值”:57
}, {
“名称”:“第1行”,
“日期”:“2017-02-09T07:13:41Z”,
“价值”:11
}, {
“名称”:“第1行”,
“日期”:“2016-11-16T21:18:03Z”,
“价值”:12
}, {
“名称”:“第1行”,
“日期”:“2016-05-01T03:08:22Z”,
“价值”:71
}, {
“名称”:“第1行”,
“日期”:“2016-10-01T08:15:08Z”,
“价值”:64
}, {
“名称”:“第1行”,
“日期”:“2016-07-27T09:58:43Z”,
“价值”:25
}, {
“名称”:“第1行”,
“日期”:“2016-04-15T12:20:35Z”,
“价值”:15
}, {
“名称”:“第1行”,
“日期”:“2016-11-01T11:51:14Z”,
“价值”:69
}, {
“名称”:“第1行”,
“日期”:“2016-10-05T23:27:50Z”,
“价值”:12
}, {
“名称”:“第1行”,
“日期”:“2016-11-11T21:53:45Z”,
“价值”:87
}, {
“名称”:“第1行”,
“日期”:“2017-01-22T17:22:10Z”,
“价值”:10
}, {
“名称”:“第1行”,
“日期”:“2016-07-18T23:33:03Z”,
“价值”:27
}, {
“名称”:“第1行”,
“日期”:“2017-01-04T14:35:53Z”,
“价值”:6
}, {
“名称”:“第1行”,
“日期”:“2016-11-10T07:17:06Z”,
“价值”:91
}, {
“名称”:“第1行”,
“日期”:“2016-04-18T00:40:18Z”,
“价值”:56
}, {
“名称”:“第1行”,
“日期”:“2016-06-23T11:27:18Z”,
“价值”:22
}, {
“名称”:“第1行”,
“日期”:“2016-08-10T12:53:00Z”,
“价值”:18
}, {
“名称”:“第1行”,
“日期”:“2016-09-02T17:24:51Z”,
“价值”:89
}, {
“名称”:“第1行”,
“日期”:“2016-06-08T03:09:20Z”,
“价值”:27
}, {
“名称”:“第1行”,
“日期”:“2016-10-30T17:54:30Z”,
“价值”:38
}, {
“名称”:“第1行”,
“日期”:“2017-01-22T01:56:44Z”,
“价值”:99
}, {
“名称”:“第1行”,
“日期”:“2016-06-02T19:58:44Z”,
“价值”:48
}, {
“名称”:“第1行”,
“日期”:“2016-07-12T01:04:56Z”,
“价值”:68
}, {
“名称”:“第1行”,
“日期”:“2016-09-23T07:30:45Z”,
“价值”:11
}, {
“名称”:“第1行”,
“日期”:“2016-11-08T05:18:12Z”,
“价值”:29
}, {
“名称”:“第1行”,
“日期”:“2017-01-24T03:46:43Z”,
“价值”:19
}, {
“n