2017-06-03 68 views
0

我從我的.html文件引用.js文件,並試圖我SVG圖表追加到特定的div的。不過,我得到在控制檯下面的消息時,我打開HTML文件:SVG陣列不可用HTML頁面

TypeError: svg[0] is undefined 

當我包括我的html和我的script.js代碼沿腳本標籤,我可以找到「SVG」陣列(和預期的餅圖)從控制檯。 [我使用這些數據在下面的stack.js結尾創建了forEach循環。]我知道stack.js代碼的工作原理,因爲它與我前幾天發佈的this question的代碼相同。

我很好奇,爲什麼我不能讓我的.html文件「看到」從我的js文件的陣列。有沒有辦法做到這一點,或者我錯過了我應該使用d3的最佳做法?它與d3 being asynchronous有什麼關係?

stack.html:

<!doctype html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
    <script src="stack.js"></script> 
</head> 

<body> 
    <div id="pie1"></div> 
    <div id="pie2"></div> 
</body> 
</html> 

stack.js

var data = { 
    "data":[ 
     {"pie_one": { 
      "id": "pie1", 
      "results": [ 
       {"ratio": 0.04, "total": 7, "failures": 1}, 
       {"ratio": 0.04, "total": 8, "failures": 0}, 
       {"ratio": 0.04, "total": 9001, "failures": 0} 
      ]} 
     }, 
     {"pie_two": { 
      "id": "pie2", 
      "results": [ 
       {"ratio": 0.04, "total": 10, "failures": 0}, 
       {"ratio": 0.04, "total": 11, "failures": 1}, 
       {"ratio": 0.04, "total": 12, "failures": 1} 
      ]} 
     } 
    ] 
}; 

var width = 300, 
    height = 300, 
    radius = Math.min(width, height)/2; 

var arc = d3.svg.arc() 
    .outerRadius(radius) 
    .innerRadius(radius - (radius/2)); 

var pie = d3.layout.pie() 
    .sort(null) 
    .value(function(d) { return d.ratio; }); 

var svg = d3.select("body").selectAll("svg") 
    .data(data.data) 
    .enter() 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height) 
    .append("g") 
    .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); 

svg[0].forEach(function(pie) { 
     var div = document.getElementById(pie.__data__.id); 
     div.innerHTML = pie; 
    }); 

var g = svg.selectAll(".arc") 
    .data(function(d,i) { return pie(d["pie"+(i+1)].results) }) 
    .enter().append("g") 
    .attr("class", "arc") 

    g.append("path") 
    .attr("d", arc) 
    .style("fill", function(d) { return (d.data.failures > 0) ? "#d63535" : "#22c12d"; }); 

window.onload = function() { 
    svg[0].forEach(function(pie) { 
     var div = document.getElementById(pie.__data__.id); 
     div.innerHTML = pie; 
    }); 
}; 
+0

爲什麼你在forEach中使用'svg [0]',是不是'svg'? –

+0

@AhmedMasud這裏是控制檯對於svg :(陣列[數組[2]])和svg [0]的結果:(陣列[,]) – Drew

+1

您正試圖訪問DOM元素你的DOM是建立的。你應該把所有的代碼移到你的onload函數中。但絕對是它處理任何文檔相關對象的部分。 – clockwatcher

回答

2

,你不能引用您的SVG的原因[0] is--正如我在提到我評論 - 因爲你正在嘗試在DOM加載之前做些事情。將你的代碼移動到window.onload中可以解決這個特定的錯誤,但是你在嘗試做事情時會遇到其他問題。

下面是一個工作示例,更你想要做什麼。您應該使用d3的功能將圖表嵌入您想要的位置。而不是把它們粘在身體裏,然後試着移動它們。

stack.js

var data = { 
    "data":[ 
     { 
      "id": "pie1", 
      "results": [ 
       {"ratio": 0.04, "total": 7, "failures": 1}, 
       {"ratio": 0.04, "total": 8, "failures": 0}, 
       {"ratio": 0.04, "total": 9001, "failures": 0} 
      ] 
     }, 
     { 
      "id": "pie2", 
      "results": [ 
       {"ratio": 0.04, "total": 10, "failures": 0}, 
       {"ratio": 0.04, "total": 11, "failures": 1}, 
       {"ratio": 0.04, "total": 12, "failures": 1} 
      ] 
     } 
    ] 
}; 

window.onload = function() { 

var width = 300, 
    height = 300, 
    radius = Math.min(width, height)/2; 

var arc = d3.svg.arc() 
    .outerRadius(radius) 
    .innerRadius(radius - (radius/2)); 

var pie = d3.layout.pie() 
    .sort(null) 
    .value(function(d) { return d.ratio; }); 

var svg = d3.select("body") 
    .selectAll("div") 
    .data(data.data, function(d) { return d ? d.id : this.id }) 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height) 
    .append("g") 
    .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); 

var g = svg.selectAll(".arc") 
    .data(function(d) { return pie(d.results) }) 
    .enter().append("g") 
    .attr("class", "arc") 
    .append("path") 
    .attr("d", arc) 
    .style("fill", function(d) { return (d.data.failures > 0) ? "#d63535" : "#22c12d"; }); 

}; 

的關鍵,讓你想讓他們是在數據綁定呼叫的第二個參數的圖表。

.selectAll("div") 
    .data(data.data, function(d) { return d ? d.id : this.id }) 

rows--其中那些密鑰匹配,D3結合該特定數據行,用以對數據元素進行上述生成用於兩個元件和數據的密鑰值。

我也改變了你的數據結構一點點,因爲你正在做獨特的按鍵事識別您的對象的方式使得它很難與數據D3的思想工作。如果出於某種原因無法更改數據結構,那麼我會建議一箇中間函數來將數據重塑爲更易於使用的內容。上一個問題中的另一張海報也對您的數據結構進行了評論。

您的stack.html保持不變。

<!doctype html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
    <script src="stack.js"></script> 
</head> 

<body> 
    <div id="pie1"></div> 
    <div id="pie2"></div> 
</body> 
</html>