我正在尝试实现一种功能,用户可以通过复选框过滤D3强制布局。我试着用几个例子来解决这个问题,最后开始使用这个例子,其中使用这些函数实现过滤:
function createFilter() {
//alert("createFilter");
d3.select(".filterContainer").selectAll("div")
.data(["6UGSWD8D", "7V9JCFSV", "AFWXF8CH", "HTFNIQDD"])
.enter()
.append("div")
.attr("class", "checkbox-container")
.append("label")
.each(function (d) {
// create checkbox for each data
d3.select(this).append("input")
.attr("type", "checkbox")
.attr("id", function (d) {
return "chk_" + d;
})
.attr("checked", true)
.on("click", function (d, i) {
// register on click event
var lVisibility = this.checked ? "visible" : "hidden";
filterGraph(d, lVisibility);
})
d3.select(this).append("span")
.text(function (d) {
return d;
});
});
$("#sidebar").show();
}
function filterGraph(aType, aVisibility) {
// change the visibility of the connection link
link.style("visibility", function (o) {
var lOriginalVisibility = $(this).css("visibility");
return o.certainty === aType ? aVisibility : lOriginalVisibility;
});
// change the visibility of the node
// if all the links with that node are invisibile, the node should also be invisible
// otherwise if any link related to that node is visibile, the node should be visible
node.style("visibility", function (o, i) {
var lHideNode = true;
link.each(function (d, i) {
if (d.source === o || d.target === o) {
if ($(this).css("visibility") === "visible") {
lHideNode = false;
// we need show the text for this circle
d3.select(d3.selectAll(".nodeText")[0][i]).style("visibility", "visible");
return "visible";
}
}
});
if (lHideNode) {
// we need hide the text for this circle
d3.select(d3.selectAll(".nodeText")[0][i]).style("visibility", "hidden");
return "hidden";
}
});
}
现在,我面临一个错误,指出链接未定义。根据我的理解,可能是因为变量链接尚未在函数范围内定义。但是,“link”和“node”都已在绘制布局的main函数内定义:
d3.json("graph.json", function(error, graph) {
if (error) throw error;
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 5)
// .text(function(d) { return d.name })
//.attr("fill", function(d) { return color(d.group); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var text = svg.append("svg:g")
.selectAll("g")
.data(simulation.nodes())
.enter().append("svg:g")
.attr("class", "nodeText");
// A copy of the text with a thick white stroke for legibility.
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("class", "shadow")
.text(function (d) {
return d.id;
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
});
有没有办法维护主函数的编写方式,同时使用这两个函数来创建过滤效果?