2017-05-29 25 views
0

如何解決未定義的數據問題基於使用d3.v3.min.js的示例Histogram chart using d3js我也創建了一個直方圖。然而,在調用片段時:當調用d3.layout.histogram()。bin(...)(...)

// Generate a histogram using twenty uniformly-spaced bins. 
var data = d3.layout.histogram() 
    .bins(x.ticks(20)) 
    (values); 
if (angular.isUndefined(data) || data.length === 0) { 
    // what now??? 
} 

,如果值只有一個獨特的價值(可在我的使用情況發生),那麼上面的會導致不確定的數據如當var values = [1., 1., 1., 1., 1., 1., 1.]

有沒有辦法確保我總是得到至少一個有效的斌而不是未定義的數據爲這個邊界案件?我已準備the following JSFiddle重現問題。只要確保打開控制檯以查看錯誤和callstack例如在IE F12或Firefox中使用開發工具。

回答

2

您問題的根本原因是使用x.ticks來設置您的垃圾箱。當你只有一個值,這導致minmax是相同的值,你這裏有沒有域:

var x = d3.scale.linear() 
    .domain([min, max]) 
    .range([0, width]); 

你可以阻止這種用簡單的檢查:

var max = d3.max(values); 
var min = d3.min(values); 
if (max === min){ 
    max += 0.1; 
    min -= 0.1; 
}  
var x = d3.scale.linear() 
     .domain([min, max]) 
     .range([0, width]); 

運行代碼:

var color = "steelblue"; 
 

 
//var values = d3.range(1000).map(d3.random.normal(20, 5)); 
 
var values = d3.range(1000).map(function (idx) {return 1.0; }); 
 

 
// A formatter for counts. 
 
var formatCount = d3.format(",.0f"); 
 

 
var margin = {top: 20, right: 30, bottom: 30, left: 30}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var max = d3.max(values); 
 
var min = d3.min(values); 
 

 
if (max === min){ 
 
\t max += 0.1; 
 
    min -= 0.1; 
 
} 
 

 
var x = d3.scale.linear() 
 
     .domain([min, max]) 
 
     .range([0, width]); 
 

 
var data = d3.layout.histogram() 
 
    .bins(x.ticks(20)) 
 
    (values); 
 
    
 
    console.log(data) 
 

 
var yMax = d3.max(data, function(d){return d.length}); 
 
var yMin = d3.min(data, function(d){return d.length}); 
 
var colorScale = d3.scale.linear() 
 
      .domain([yMin, yMax]) 
 
      .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]); 
 

 
var y = d3.scale.linear() 
 
    .domain([0, yMax]) 
 
    .range([height, 0]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom"); 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var bar = svg.selectAll(".bar") 
 
    .data(data) 
 
    .enter().append("g") 
 
    .attr("class", "bar") 
 
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 

 
bar.append("rect") 
 
    .attr("x", 1) 
 
    .attr("width", (x(data[0].dx) - x(0)) - 1) 
 
    .attr("height", function(d) { return height - y(d.y); }) 
 
    .attr("fill", function(d) { return colorScale(d.y) }); 
 

 
bar.append("text") 
 
    .attr("dy", ".75em") 
 
    .attr("y", -12) 
 
    .attr("x", (x(data[0].dx) - x(0))/2) 
 
    .attr("text-anchor", "middle") 
 
    .text(function(d) { return formatCount(d.y); }); 
 

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

 
/* 
 
* Adding refresh method to reload new data 
 
*/ 
 
function refresh(values){ 
 
    // var values = d3.range(1000).map(d3.random.normal(20, 5)); 
 
    var data = d3.layout.histogram() 
 
    .bins(x.ticks(20)) 
 
    (values); 
 

 
    // Reset y domain using new data 
 
    var yMax = d3.max(data, function(d){return d.length}); 
 
    var yMin = d3.min(data, function(d){return d.length}); 
 
    y.domain([0, yMax]); 
 
    var colorScale = d3.scale.linear() 
 
       .domain([yMin, yMax]) 
 
       .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]); 
 

 
    var bar = svg.selectAll(".bar").data(data); 
 

 
    // Remove object with data 
 
    bar.exit().remove(); 
 

 
    bar.transition() 
 
    .duration(1000) 
 
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 

 
    bar.select("rect") 
 
     .transition() 
 
     .duration(1000) 
 
     .attr("height", function(d) { return height - y(d.y); }) 
 
     .attr("fill", function(d) { return colorScale(d.y) }); 
 

 
    bar.select("text") 
 
     .transition() 
 
     .duration(1000) 
 
     .text(function(d) { return formatCount(d.y); }); 
 

 
}
body { 
 
    font: 10px sans-serif; 
 
} 
 

 
.bar rect { 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.bar text { 
 
    fill: #999999; 
 
} 
 

 
.axis path, .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>