【问题标题】:how to load json variable into D3?如何将 json 变量加载到 D3 中?
【发布时间】:2018-11-04 05:04:51
【问题描述】:

我是 D3 的新手。我有一个很好的example of a candlestick chart,它可以从 csv 文件中加载它的数据。我得到了那个例子,但现在我想做同样的事情,除了从返回 json 数据的 ajax 调用中加载数据。我不知道该怎么做。

看了几篇cmets,下面是我的第二次尝试:

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。这是每个的sn-p:

getQuoteHistory:data="[{\"符号\":\"A\",\"日期\":\"2018-06-28\",\"开盘\":\"61.13\", \"高\":\"61.64\",\"低\":\"60.42\",\"收盘\":\"61.29\",\"音量\":\"15641\"},{ \"符号\":\"A\",\"日期\":\"2018-06-29\",\"开盘\":\"61.68\",\"高位\":\"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 文件工作?

【问题讨论】:

  • 看来您正在使用 jquery 来获取数据。你不需要!如果是json文件,使用d3.json,如果是csv,使用d3.csv获取远程数据。
  • 还请显示您在登录data 时看到的内容。该错误可能告诉您data 不是数组。
  • 确保您的 JSON 记录中有相同的字段,否则 candlestick.accessor() 将找不到数据。
  • 我在 timeParse 中有一个小写的“y”而不是大写的“Y”。还需要使用 data = JSON.parse(data) 将传入的 json 解析为 javascript。现在问题已经变成了修改后的版本。
  • @jrook: 如何使用 d3.json(... ?据我所知,它需要一个文件。我没有文件,我有一个变量。跨度>

标签: javascript json d3.js


【解决方案1】:

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

只需添加:

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

【讨论】:

  • 我尝试了您的建议,它确实结束了该错误,但产生了一个新错误“错误: 属性 d:预期数字,“…700742432895511 NaN l 10.4671616…”。我正在考虑将答案归功于您,但上面的@rioV8 评论让我担心这可能不是正确的答案。
  • 您的 svg 变量必须在 draw(data) 函数中定义。在您的代码中,它是未定义的。 @rioV8 也是对的:您可以在父作用域上定义它,将其作为参数传递,或者在绘图函数中重新选择它。但是您的第二条错误消息与您的数据本身或缩放方法有关,因为错误消息中有一个 NaN。
【解决方案2】:

这是工作代码。感谢所有的贡献者。我从你们每个人那里学到了如何让它发挥作用。

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 内容。

【讨论】:

    猜你喜欢
    • 2011-01-11
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 2013-01-07
    相关资源
    最近更新 更多