我正在使用d3中的散点图。图上的点代表一张纸。右键单击一个点,我有一个上下文菜单,其中有2个选项:1)将纸张添加到库中(将类型更改为In_library)和2)从库中删除(从数据中完全删除纸张)。
在每个更新之后,我都会调用refreshGraph()函数,该函数将使用更新后的数据重绘图形。但是我认为没有发生任何事情是因为refreshGraph()没有被正确调用吗?还是对于选项1类型库设置不正确?当在选项1之后调用refreshGraph时,该点应变为蓝色,而在为选项2调用该点时,该点应从显示中消失,因为该点已从alldata(用于绘制圆的数据)中删除。以下是相关代码:
allData = [];
var menu = [{
title: 'Add to Library',
action: function addToLibrary(elem, d, i) {
d3.json("connection6.php?paperID="+d.ID, function(error, dataJson) {
for(i=0;i<allData.length;i++){
if (d.type === "In_library")
{
alert("The paper: " + d.TITLE + " is already in your Library!");
return;
}
}
d.type = "In_library"; // is this the correct way to change the type if the input has a different type??
refreshGraph();
})
refreshGraph();
}
},
{
title: 'Remove from Library',
action: function removeFromLibrary (elem, d, i) {
d3.json("connection9.php?paperID="+d.ID, function(error, dataJson) {
//loop through allData and if selected ID has type In_library, remove from allData
for(i=0;i<allData.length;i++){
if (d.type == "In_library"){
allData.splice(i--,1);
}
}
refreshGraph();
})
}
}
]
function refreshGraph() {
// draw dots
var circles = svg.selectAll("circle")
.data(allData)
circles.transition()
.attr("cx", function(d) {return x(YearFn(d))})
.attr("cy", function(d) {return y(Num_citationsFn(d))})
circles.enter()
.append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) {return x(YearFn(d))})
.attr("cy", function(d) {return y(Num_citationsFn(d))})
.style("fill",function(d){
var colour = "black"
switch(d.type){
case "In_library":
colour = "blue";
break;
case "cited by":
colour = "red";
break;
case "cites":
colour = "green";
break;
case "selected":
colour = "magenta";
break;
default:
colour = "black";
}
return colour;
})
.on("mouseover", mouseHandler)
.on("mouseout", mouseoutHandler)
.on("click", clickHandler)
.on("contextmenu", rightClickHandler);
svg.select(".y.axis").call(yAxis);
svg.select(".x.axis").call(xAxis);
//don't want dots overlapping axis, so add in buffer to data domain
x.domain([d3.min(allData, YearFn)-1, d3.max(allData, YearFn)+1]);
y.domain([d3.min(allData, Num_citationsFn)-1, d3.max(allData, Num_citationsFn)+1]);
}
非常感谢任何帮助,我是d3的新手,所以在此先感谢!
最佳答案
您无需在每次更改单个点时重新绘制所有数据。只需更新这一点即可。
function rightClickHandler() {
// if option 1
d3.select(this).style("fill", "blue");
// if option 2
d3.select(this).remove();
}
您的问题可能会出现,因为当您第二次(或第三次)调用refreshGraph时,您不清楚所绘制的圆。您的refreshGraph函数不会更新已绘制的点,而是每次都在重新创建它们。如果您不清除已存在的点,则不会看到新的点(或它们不存在,或更改中颜色),因为它们隐藏在您的旧点后面。
编辑:
如果要每次都重新添加数据,则首先必须清除现有数据。在refreshGraph函数的开始,添加以下行:
if(!d3.selectAll("circle").empty()) d3.selectAll("circle").remove();
也就是说,如果有圆形元素,请将其删除。假设您仅在refreshGraph函数内创建圆元素。如果在其他位置创建它们,则可能应改用.dot选择器。