2015-05-02 30 views
2

我正在研究一个网络工具,该工具应该创建一个给定数据的散点图。由于我对任何可视化都不熟悉(也不是JavaScript专家),所以我决定使用D3。D3放大画笔范围

以下教程,观察示例和尝试的东西我得到一个散点图与刷选择(它什么都没做)。 现在,因为目标是绘制基因,所以它们中的许多将在x和y坐标方面彼此非常接近。所以我想实现一些东西like this,但在x和y方向。基本上放大拉丝部分。

到目前为止,我无法创建此行为,此时我的坐标轴确实发生了变化,但不再显示值,也没有发生缩放。你可以在my toy subdomain上看到它。我不确定它出错的地方,所以任何帮助表示赞赏。

在玩具领域中使用的JavaScript:

// General variables 

var svg, width, height; 
var padding = 30; 

var dataset = [ 
       [ 5,  20 ], 
       [ 480, 90 ], 
       [ 250, 50 ], 
       [ 100, 33 ], 
       [ 330, 95 ], 
       [ 410, 12 ], 
       [ 475, 44 ], 
       [ 25, 67 ], 
       [ 85, 21 ], 
       [ 220, 88 ] 
      ]; 

function drawGraph(){ 
    scatterplot_area_size = $("#scatterplot").width(); 
    width = scatterplot_area_size; 
    height = scatterplot_area_size * 0.75; 

    console.log(width); 

    // Retrieve the interval of the x and y data 
    var maxX = d3.max(dataset, function(d) { 
     return d[0]; //References first value in each sub-array 
    }); 

    var minX = d3.min(dataset, function(d) { 
     return d[0]; //References first value in each sub-array 
    }); 

    var maxY = d3.max(dataset, function(d) { 
     return d[1]; //References second value in each sub-array 
    }); 

    var minY = d3.min(dataset, function(d) { 
     return d[1]; //References second value in each sub-array 
    }); 

    // Create a (square) scatterplot area in the div with id scatterplot 
    // which spans the entire div in width 
    svg = d3.select("#scatterplot") 
      .append("svg") 
      .attr("width", width) 
      .attr("height", height); 

    // plot all points 
    var points = svg.append("g") 
     .attr("class", "point") 
     .selectAll("point") 
     .data(dataset) 
     .enter() 
     .append("circle"); 


    console.log(minX + " " + minY); 

    // Create x and y scales 
    var x = d3.scale.linear() 
        .domain([minX, maxX]) 
        .range([padding, (width-padding)]); 

    var y = d3.scale.linear() 
        .domain([minY, maxY]) 
        .range([(height-padding), padding]); // Reverse the scale to let high values show at the top and low values at the bottom 

    // Set the x and y positions as well as the radius (hard coded 5) 
    points.attr("cx", function(d) { 
     return x(d[0]); 
    }) 
    .attr("cy", function(d) { 
     return y(d[1]); 
    }) 
    .attr("r", 5); 

    // Create the x and y axes 
    var xAxis = d3.svg.axis() 
        .scale(x) 
        .ticks(10) 
        .orient("bottom"); 

    var yAxis = d3.svg.axis() 
        .scale(y) 
        .ticks(10) 
        .orient("left"); 

    // Add the axes to the scatterplot 
    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + (height-padding) + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .attr("transform", "translate(" + padding + ",0)") 
     .call(yAxis); 

    // Allow for brushing (selection of points) 
    var brush = d3.svg.brush() 
     .x(x) 
     .y(y) 
     .on("brush", brushmove) 
     .on("brushend", brushend); 

    svg.append("g") 
     .attr("class", "brush") 
     .call(brush) 
     .selectAll('rect') 
     .attr('height', height); 

    function brushmove() { 
     var extent = brush.extent(); 
     points.classed("selected", function(d) { 
     return extent[0][0] <= d[0] && d[0] <= extent[1][0] 
       && extent[0][1] <= d[1] && d[1] <= extent[1][1]; 
     }); 
    } 

    function brushend() { 
     x.domain(brush.extent()); 
     y.domain(brush.extent()); 

     transition_data(); 
     reset_axis(); 

     points.classed("selected", false); 
     d3.select(".brush").call(brush.clear()); 
    } 

    function transition_data() { 
     console.log("transistion data called"); 
     d3.selectAll("point") 
     .transition() 
     .duration(500) 
     .attr("cx", function(d) { console.log(d[0]); return x(d[0]); }) 
     .attr("cy", function(d) { return y(d[1]); }); 
    } 

    function reset_axis() { 
     svg.transition().duration(500) 
     .select(".x.axis") 
     .call(xAxis); 

     svg.transition().duration(500) 
     .select(".y.axis") 
     .call(yAxis); 
    } 
} 

// Wait until the document is loaded, then draw the graph. 
$(document).ready(function() { 
    drawGraph(); 
}); 

// If the window is resized, redraw graph to make it fit again. 
$(window).resize(function() { 
    if(typeof svg != 'undefined'){ 
     $("#scatterplot").empty(); 
    } 
    drawGraph(); 
}); 
+0

您是否收到任何错误消息? –

+0

不,我的控制台显示没有错误或警告 – Gooey

回答

4

有两个错误在你的代码:

  1. 在你的函数brushend()您正在使用的返回值设置你的尺度域在这两种情况下都是brush.extent()。但是,请注意,画笔返回的范围是一个二维数组,如[[xMin,yMin],[xMax,yMax]]。您必须设置您的域使用

    var extent = brush.extent(); 
    x.domain([extent[0][0],extent[1][0]]); // x.domain([xMin,xMax]) 
    y.domain([extent[0][1],extent[1][1]]); // y.domain([yMin,yMax]) 
    

    这些调整将使您的轴正确缩放,而点仍然是固定的。

  2. 您在d3.selectAll("point")中插入和操作您的数据点,将其称为svg:point。但是,没有这种类型的svg元素。尽管您致电d3.selectAll("point")仍然有效,但它总是会产生一个空的选择,因为没有要选择的元素。因为这个原因,你在设置svg时第一次调用这个函数确实有效,因为它会把所有绑定到输入选择的数据提供给你想要的结果。对于正确性的缘故,你应该纠正这

    // plot all points 
    var points = svg.append("g") 
        .attr("class", "point") 
        // .selectAll("point") 
        .selectAll("circle") // <-- This will work 
        .data(dataset) 
        .enter() 
        .append("circle"); 
    

    当试图将其具有的尺度域故障代码不会在这种情况下,空选择是没有意义的,因为工作后更新您的点,将没有任何效果在任何元素上。由于在上面引用的声明中,您已经在var points中存储了对您的选择的参考,因此无需再次选择它们。你可以只重写你的更新内容如下:

    function transition_data() { 
        // d3.selectAll("point") // Instead of this... 
        points      // <-- ...use the reference to your selection 
         .transition() 
         .duration(500) 
         .attr("cx", function(d) { return x(d[0]); }) 
         .attr("cy", function(d) { return y(d[1]); }); 
    } 
    

我放在一起工作JSFiddle演示解决方案。

+0

哦,哇,我不知道这个程度是一个二维数组。非常感谢您的解释,这很清楚。 – Gooey