2015-05-02 27 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