0

我对 D3 和 Javascript 非常陌生,所以如果我的代码看起来有点丑陋或组织不佳,请原谅我。

我一直在研究一个利用 3 个指标的图:x 和 y 轴,以及圆的半径作为图的数据指标。我正在读取的数据是一个二维数组,每一行是一个不同的指标,每一列是一个新的数据点。我已经成功地实现了一种通过从下拉框中选择不同的度量来动态更改圆半径的方法,但这是在无休止地解决一个非常特殊的问题之后 - 我的数据被分配到了错误的圆!

当我最初创建我的圆圈时,我首先使用 sort() 从默认半径度量(在我的代码中,它的“impactcpu”)按降序对圆圈进行排序。这样做是为了解决在较小圆圈之后绘制的较大圆圈阻碍较小圆圈的问题,因此我想先“绘制”最大的圆圈。

我能够通过首先对我的计算数据数组进行排序,然后将其分配给圆圈来解决这个问题,这保留了默认顺序。但是,我现在正尝试对我的 X 和 Y 轴做类似的事情。虽然我的下拉菜单正确地将度量值分配给圆圈,但它正在为错误的圆圈这样做。我还没有找到解决这个问题的方法,因为在分配之前对数组重新排序就像我在半径不工作时所做的那样(这是我所期望的)。关于如何确保将正确的数据点分配给正确的圆圈有什么建议吗?最好是不需要对我的其余代码进行大修的一个:)

请查看我的 jsfiddle 以了解上述情况的示例:

http://jsfiddle.net/kingernest/YDQR4/3/

我最初创建圈子的示例:

var circles = svg.selectAll("circle")
    .data(dataset, function(d) { return d.id })
    .enter()    
    .append("circle")
    .sort(function(a, b){    //Sort by radius size, helps reduce obstruction of circles
        return d3.descending(a[14], b[14]);
    })
    .attr("cx", function(d){ //x axis is Req IO, col index 9
        return xScale(d[9]);
    })
    .attr("cy", function(d){ //y axis is Req CPU, col index 8
        return yScale(d[8]);
    })
    .attr("r", function(d){ //radius is based off Impact CPU, col 14

        console.log("Rad: " + d[14])
        return d[14] * 1.5;
    })
    .attr("class", "dataCircle")

ETC

我目前如何改变我的半径:

function changeRad() {
     console.log(this.value); 
     var myRadData = [];
     var index = metricHash[this.value];
     var weight; //to adjust data to fit appropriately in graph
    switch(this.value) 
    {
        case "impactcpu": 
            weight = 1.5;
            break;
        case "spool": 
            weight = .0000001;    //spool is normally a very large value
            break;
        case "pji": 
            weight = 8;
            break;
        case "unnecio": 
            weight = 12;
            break;
        case "duration": 
            weight = .0002;
            break;
        default: alert("Invalid value: " + this.value); 
            break;
    }
     for(var i=0; i < dataset.length; i++)
     {         
         console.log(dataset[i][index]);
         myRadData.push(dataset[i][index] * weight);
     }

    myRadData.sort(function(a,b){return b-a});

    d3.selectAll("circle")
        .data(myRadData)
        .transition().duration(500)
        .attr("r", function(d){
            return d;
        });

    circles.data(dataset); //reassign old data set (with all data values)
}
4

2 回答 2

1

我不确定我是否掌握了你的整个代码(它很长),但我认为解决方案如下:

1 - 最初创建圆圈时,请使用键功能。很好,你正在这样做:

.data(dataset, function(d) { return d.id; })

2 - 使用相同的函数为圆圈赋予 ID 属性:

.attr("ID", function(d) { return d.id; })

3 - 然后,当您需要单独修改特定圆圈时,您可以像这样选择它:

svg.select('#' + myCircleID).attr('blahblah', somevalue)

我还注意到您在构建 myRadData 数组时丢失了 ID 属性。这将阻止代码将它们加入正确的圈子。由于您在开始时有一个 ID 属性,因此您最好始终使用键功能,而不是尝试使用排序来排列。

如果您想要更具体的答案,我认为您需要将示例归结为重现问题的最简单形式。

于 2013-03-06T02:07:58.747 回答
1

我在您的代码中看到了两件事:

  1. 数据绑定上的键功能不一致 - 您在初始创建圆(.data(dataset, function(d) { return d.id }))时正确使用它,但在更新它们时不要引用它,在更新上添加相同的键将确保您更新相同的元素。

  2. DOM 排序 - 您在最初创建圈子时使用 selection.sort 似乎合乎逻辑且合适(.sort(function(a, b){ return d3.descending(a[14], b[14]); }))我建议将其扩展到您的更新函数,而不是重新绑定数据。

我已经对您的代码进行了这些快速更新,它似乎可以解决您的问题:http: //jsfiddle.net/AbHfk/3/

于 2013-03-06T02:37:08.473 回答