2016-10-04 49 views
0

我想使用.json文件製作散點圖。它會讓用戶選擇要顯示的json文件中的哪一組數據。所以我試圖使用更新模式。D3圖表無法更新 - 輸入和退出選擇屬性都爲空

以下代碼將生成第一張圖,但每次調用selectGroup()(代碼位於html文件中)時,都沒有更新。 console.log(選擇)每次都返回一個新數組,但該選擇的輸入和退出屬性始終爲空。 任何人都可以幫我看一下嗎?非常感謝!

var margin = { 
    top: 30, 
    right: 40, 
    bottom: 30, 
    left: 40 
} 
var width = 640 - margin.right - margin.left, 
    height = 360 - margin.top - margin.bottom; 
var dataGroup; 
var groupNumDefault = "I"; 
var maxX, maxY; 
var svg, xAxis, xScale, yAxis, yScale; 



//select and read data by group 
function init() { 
    d3.json("data.json", function (d) { 
     maxX = d3.max(d, function (d) { 
      return d.x; 
     }); 
     maxY = d3.max(d, function (d) { 
      return d.y; 
     }); 
     console.log(maxY); 

     svg = d3.select("svg") 
      .attr("id", "scatter_plot") 
      .attr("width", 960) 
      .attr("height", 500) 
      .append("g") 
      .attr("id", "drawing_area") 
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

     //x-axis 
     xScale = d3.scale.linear().range([0, width]).domain([0, maxX]); 
     xAxis = d3.svg.axis() 
      .scale(xScale).orient("bottom").ticks(6); 

     //y-axis 
     yScale = d3.scale.linear().range([0, height]).domain([maxY, 0]); 
     yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(6); 

     svg.append("g") 
      .attr("class", "x_axis") 
      .attr("transform", "translate(0," + (height) + ")") 
      .call(xAxis); 

     svg.append("g") 
      .attr("class", "y_axis") 
      .call(yAxis); 

    }); 

    selectGroup(groupNumDefault); 
} 

//update data 
function selectGroup(groupNum) { 
    d3.json("/data.json", function (d) { 
     dataGroup = d.filter(function (el) { 
      return el.group == groupNum; 
     }); 
     console.log(dataGroup); 
     drawChart(dataGroup); 

    }); 
} 


//drawing function 
function drawChart(data) { 
    var selection = d3.select("svg").selectAll("circle") 
     .data(data); 
    console.log(selection); 

    selection.enter() 
     .append("circle") 
     .attr("class", "dots") 
     .attr("cx", function (d) { 
      console.log("updating!"); 
      return xScale(d.x); 
     }) 
     .attr("cy", function (d) { 
      return yScale(d.y); 
     }) 
     .attr("r", function (d) { 
      return 10; 
     }) 
     .attr("fill", "red"); 

    selection.exit().remove(); 
} 

init(); 

回答

0

這裏的問題是在兩個方面:


首先,你的缺乏在data()呼叫的鍵功能的裝置的數據由索引通過默認,匹配的(在數據陣列位置),該如果發送到data()的舊數據集和當前數據集的大小相同,則表示沒有進入和退出選擇。相反,當d3與索引匹配時(舊數據集中的第一個數據=新數據集中的第一個數據,舊數據集中的第二個數據=新數據集中的第二數據等)等,大多數(可能全部)數據將被放入更新選擇中)

var selection = d3.select("svg").selectAll("circle") 
     .data(data); 

參見:https://bl.ocks.org/mbostock/3808221

基本上,你需要你的數據呼叫調整到這樣的事情(如果你的數據是否有.ID財產或者其他任何可以唯一地識別每個數據)

var selection = d3.select("svg").selectAll("circle") 
      .data(data, function(d) { return d.id; }); 

這將根據數據的實際內容(而不僅僅是它們的索引)生成enter()和exit()(和update)選擇。其次,並非所有第二次回合都保證在進入或退出選擇中。有些數據可能只是現有數據的更新,而不是這兩種選擇中的任何一種(在您的情況下,它可能每次都是全新的)。但是,考慮到上面描述的情況,幾乎可以保證大部分數據都在更新選擇中,其中一些是錯誤的。要顯示的更新,你將需要改變這樣的代碼(我在這裏假設D3 V3,顯然這對V4略有不同)

selection.enter() 
     .append("circle") 
     .attr("class", "dots") 
     .attr("r", function (d) { 
      return 10; 
     }) 
     .attr("fill", "red"); 

// this new bit is the update selection (which includes the just added enter selection 
// now, the syntax is different in v4) 
selection // v3 version 
// .merge(selection) // v4 version (remove semi-colon off preceding enter statement) 
     .attr("cx", function (d) { 
      console.log("updating!"); 
      return xScale(d.x); 
     }) 
     .attr("cy", function (d) { 
      return yScale(d.y); 
     }) 

    selection.exit().remove(); 

這兩個變化應看到可視化的工作,當然,除非問題像第二次空數據集這樣簡單的事情也會解釋一些事情:-)