我正在使用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选择器。

08-07 11:09