首页 > 解决方案 > how to load json variable into D3?

问题描述

I'm a newbie at D3. I have this nice example of a candlestick chart that loads its data from a csv file. I got that example to work but now I want to do the same thing except load the data from an ajax call which returns json data. I can't figure out how to do it.

After reading a few comments, here is my second attempt:

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);
    }
}

The ajax call returns good json array data and it is converted to newData which has the date parsed correctly and the field names in lower case as reqd. Here is a snippet of each:

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\",\"Low\":\"61.57\",\"Close\":\"61.84\",\"Volume\":\"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",

Now the failure happens in the draw function on this line:

svg.selectAll("g.candlestick").datum(data).call(candlestick);  

where the chrome javascript console shows "svg is not defined".

But it is defined in the html:

    <svg></svg>

Even if I pass svg as a parameter to draw method, then it says "cannot read property selectAll of undefined".

Any ideas how to get this to work from a json array instead of a csv file?

标签: javascriptjsond3.js

解决方案


你需要重新选择你的svgin function draw(data),因为你的变量var svg是一个局部变量,它只在success你的 ajax 调用的函数中定义。

只需添加:

function draw(data) {
  var svg = d3.select("svg");
  // The rest of your function
}

推荐阅读