我在D3中有一个条形图,我想使用自定义函数update_bars()更新条形图。每个rect元素都被赋予一个从0到9的id。该函数应该通过id选择rect然后更改width属性,但我得到“this.setAttribute”不是函数。但是,当我使用普通的旧JavaScript时,它工作正常。我已经评论了哪里出了问题。
<!DOCTYPE>
<html>
<head>
<link rel="shortcut icon" href="">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
<!-- everything works fine here -->
var width = 800, barHeight = 20, height = barHeight*10;
var chart = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var init_year = 2000;
d3.json("topten.json", function(data){
the_data = data;
var bar = chart.selectAll("g")
.data(data[init_year])
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate(0," + i * barHeight + ")";
})
bar.append("rect")
.attr("width", function(d){
return d['articles']
})
.attr("height", barHeight - 1)
.attr("id", function(d,i){ return i; } );
});
<!-- problem is in update_bars() -->
function update_bars(data, yr){
data[yr].forEach( function(d, i){
<!-- this d3 code gives "this.setAttribute is not a function" error -->
/. d3.select(i).attr("width", d['articles']); ./
<!-- this javascript works -->
temp = document.getElementById(i);
temp.setAttribute("width", d['articles']);
});
}
</script>
</body>
</html>
答案 0 :(得分:2)
首先,为了按ID进行选择,您需要在#
d3.select("#myID")
之前为选择器添加序号:id
但另一个问题是,您的代码是使用此行向<rec id="1">
这样的单个数字的每个矩形分配.attr("id", function(d,i){ return i; } );
:
d3.select("#" +i)
这会导致选择器出现问题,因为您需要使用d3.select("#\\31")
选择此选项,但这不会起作用。选择带有前导数字的ID非常痛苦,除非你愿意用这样的unicode代码点选择每一个:
id
(详见此处:Using querySelector with IDs that are numbers)
更好的计划是为每个rect
分配不同的.attr("id", function(d,i){ return "_" + i; } );
,例如:
d3.select("#_" + i).attr()
然后您可以选择:
Public Sub btcteste()
Dim xmlhttp As Object
'Dim xmlhttp As New MSXML2.ServerXMLHTTP60
Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP")
Dim myurl As String
Dim strText As String
Dim vSplit As Variant, v As Variant
Dim vR() As Variant
Dim n As Integer
myurl = "https://api.blinktrade.com/api/v1/BRL/ticker?crypto_currency=BTC"
xmlhttp.Open "GET", myurl, False
xmlhttp.send
'MsgBox (xmlhttp.responseText)
strText = xmlhttp.responseText
strText = Replace(strText, "}", "")
strText = Replace(strText, "{", "")
strText = Replace(strText, Chr(34), "")
vSplit = Split(strText, ",")
For Each v In vSplit
n = n + 1
ReDim Preserve vR(1 To 2, 1 To n)
vR(1, n) = Trim(Split(v, ":")(0))
vR(2, n) = Trim(Split(v, ":")(1))
Next v
Range("a1").Resize(n, 2) = WorksheetFunction.Transpose(vR) '<~~ this is vertical
'Range("a1").Resize(2, n) = vR '<~~ this is horisontal
End Sub
说了这么多,一般来说你不应该在d3中循环你的数据,而是使用这里所示的一般更新模式:https://bl.ocks.org/mbostock/3808234
答案 1 :(得分:0)
尝试修复代码段,我无法重现上述问题:
<!DOCTYPE>
<html>
<head>
<link rel="shortcut icon" href="">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
<!-- everything works fine here -->
var width = 800, barHeight = 20, height = barHeight*10;
var chart = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var init_year = 2000;
//d3.json("topten.json", function(data){
// the_data = data;
var data = {
2000: [
{ articles: 10 },
{ articles: 35 },
{ articles: 47 },
{ articles: 2 },
{ articles: 87 },
],
2001: [
{ articles: 5 },
{ articles: 65 },
{ articles: 23 },
{ articles: 76 },
{ articles: 18 },
],
};
var bar = chart.selectAll("g")
.data(data[init_year])
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate(0," + i * barHeight + ")";
})
bar.append("rect")
.attr("width", function(d){
return d['articles']
})
.attr("height", barHeight - 1)
.attr("id", function(d,i){ return i; } );
//});
<!-- problem is in update_bars() -->
function update_bars(data, yr){
data[yr].forEach( function(d, i){
<!-- this d3 code gives "this.setAttribute is not a function" error -->
/. d3.select(i).attr("width", d['articles']); ./
<!-- this javascript works -->
temp = document.getElementById(i);
temp.setAttribute("width", d['articles']);
});
}
setTimeout( update_bars, 1000, data, 2001 );
</script>
</body>
</html>
&#13;
请参阅代码段。它正在工作。所以这个问题似乎与提供意外/不匹配数据格式的topten.json有关,或者与错误时序调用update_bars()有关。在获取JSON文件之前。