我是D3的新手。我有一个不错的example of a candlestick chart,可以从csv文件加载其数据。我得到了该示例,但现在我想做同样的事情,只是从返回json数据的ajax调用中加载数据。我不知道该怎么做。
阅读一些评论后,这是我的第二次尝试:
function showChart() {
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = $(window).width()*0.6 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%Y-%m-%d");
var x = techan.scale.financetime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y);
$.ajax("http://www.mycom.net/getQuoteHistory.php?symbol='A'", {
success: function(data) {
console.log("getQuoteHistory:data="+JSON.stringify(data));
var accessor = candlestick.accessor();
data = JSON.parse(data);
var newData = [];
for (var i=0; i<data.length; i++) {
var o = data[i];
var newObj = {};
newObj.date = parseDate(o.Date);
newObj.open = o.Open;
newObj.high = o.High;
newObj.low = o.Low;
newObj.close = o.Close;
newObj.volume = o.Volume;
newData.push(newObj);
}
console.log("getQuoteHistory:newData="+JSON.stringify(newData));
var svg = d3.select("svg")
.data(newData)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "candlestick");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
// Data to display initially
draw(newData.slice(0, newData.length-20));
// Only want this button to be active if the data has loaded
d3.select("button").on("click", function() {
draw(newData);
}).style("display", "inline");
},
error: function() {
console.log("something went wrong in ajax call");
}
});
function draw(data) {
x.domain(data.map(candlestick.accessor().d));
y.domain(techan.scale.plot.ohlc(data, candlestick.accessor()).domain());
svg.selectAll("g.candlestick").datum(data).call(candlestick);
svg.selectAll("g.x.axis").call(xAxis);
svg.selectAll("g.y.axis").call(yAxis);
}
}
ajax调用返回良好的json数组数据,并将其转换为newData,该数据具有正确解析的日期,且字段名称小写为reqd。这是每个的摘要:
getQuoteHistory:data =“ [{\” Symbol \“:\” A \“,\” Date \“:\” 2018-06-28 \“,\” Open \“:\” 61.13 \“, \“ High \”:\“ 61.64 \”,\“ Low \”:\“ 60.42 \”,\“ Close \”:\“ 61.29 \”,\“ Volume \”:\“ 15641 \”},{ \“ Symbol \”:\“ A \”,\“ Date \”:\“ 2018-06-29 \”,\“ Open \”:\“ 61.68 \”,\“ High \”:\“ 62.47 \ “,\”低\“:\” 61.57 \“,\”关闭\“:\” 61.84 \“,\”音量\“:\” 18860 \“}}
getQuoteHistory:newData = [{“ date”:“ 2018-06-28T06:00:00.000Z”,“ open”:“ 61.13”,“ high”:“ 61.64”,“ low”:“ 60.42”, “ close”:“ 61.29”,“ volume”:“ 15641”},{“ date”:“ 2018-06-29T06:00:00.000Z”,“ open”:“ 61.68”,
现在失败发生在此行的绘制函数中:
svg.selectAll("g.candlestick").datum(data).call(candlestick);
chrome javascript控制台显示“未定义svg”的地方。
但是它在html中定义:
<svg></svg>
即使我将svg作为参数传递给draw方法,它也会显示“无法读取未定义的selectAll属性”。
有什么想法如何使它从json数组而不是csv文件工作?
答案 0 :(得分:1)
您需要在svg
中重新选择function draw(data)
,因为变量var svg
是局部变量,仅在ajax调用的success
函数中定义。< / p>
只需添加:
function draw(data) {
var svg = d3.select("svg");
// The rest of your function
}
答案 1 :(得分:0)
这是工作代码。感谢所有贡献者。我从你们每个人那里学到了要使它生效。
function showChart(symbol) {
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = $(window).width()*0.6 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%Y-%m-%d");
var x = techan.scale.financetime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y);
$.ajax("http://www.mycom.net/getQuoteHistory.php?symbol='" +symbol +"'", {
success: function(data) {
console.log("getQuoteHistory:data="+JSON.stringify(data));
var accessor = candlestick.accessor();
data = JSON.parse(data);
data = data.slice(0, 200).map(function(d) {
return {
date: parseDate(d.Date),
open: +d.Open,
high: +d.High,
low: +d.Low,
close: +d.Close,
volume: +d.Volume
};
}).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
console.log("getQuoteHistory:newData="+JSON.stringify(data));
var svg = d3.select("svg")
.data(data)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "candlestick");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
draw(data,svg);
},
error: function() {
console.log("something went wrong in ajax call");
}
});
function draw(data,svg) {
x.domain(data.map(candlestick.accessor().d));
y.domain(techan.scale.plot.ohlc(data, candlestick.accessor()).domain());
svg.selectAll("g.candlestick").datum(data).call(candlestick);
svg.selectAll("g.x.axis").call(xAxis);
svg.selectAll("g.y.axis").call(yAxis);
}
}
可能有一种方法可以使用d3.json()来避免多余的ajax内容。