【问题标题】:plots on multiple instances of graph在图形的多个实例上绘图
【发布时间】:2012-12-07 21:43:56
【问题描述】:

我正在使用 d3 库绘制一个条形图,其中包含通过 websockets 从服务器接收的 JSON 对象。但发生的情况是,每次绘制图表时,它都会绘制一个新的图表实例。所以我最终得到了多个图表。

但我希望将 JSON 数据全部绘制到同一张图上。

这是我的代码:

      ws = new WebSocket("ws://localhost:8888/dh");

      var useData = []
      //var chart;

      var chart = d3.select("body")
         .append("svg:svg")
         .attr("class", "chart")
         .attr("width", 420)
         .attr("height", 200);


      ws.onmessage = function(evt)
      {  
        var distances = JSON.parse(evt.data);
        data  = distances.miles;
        console.log(data);

        if(useData.length <= 10){
          useData.push(data)
        }
        else
        {

           var draw = function(data){        
           // Set the width relative to max data value
           var x = d3.scale.linear()
            .domain([0, d3.max(useData)])
            .range([0, 420]);

           var y = d3.scale.ordinal()
            .domain(useData)
            .rangeBands([0, 120]);

           var rect = chart.selectAll("rect")
            .data(useData)

            // enter rect
            rect.enter().append("svg:rect")
                .attr("y", y)
                .attr("width", x)
                .attr("height", y.rangeBand());

            // update rect            
            rect
                .attr("y", y)
                .attr("width", x)
                .attr("height", y.rangeBand());

           var text = chart.selectAll("text")
                .data(useData)

           // enter text
           text.enter().append("svg:text")
                .attr("x", x)
                .attr("y", function (d) { return y(d) + y.rangeBand() / 2; })
                .attr("dx", -3) // padding-right
                .attr("dy", ".35em") // vertical-align: middle
                .attr("text-anchor", "end") // text-align: right
                .text(String);

            // update text
            text
                .data(useData)
                .attr("x", x)
                .text(String);
        }
    useData.length = 0;
       }          
    }                 

如何在不断更新的图表上绘制所有点?

很遗憾 d3 无法实时处理数据并相应地更新图表,或者如果可以的话,没有明确的教程/说明如何操作。

谢谢

【问题讨论】:

    标签: javascript jquery d3.js data-visualization


    【解决方案1】:

    我的猜测是因为您每次都在创建图表:

    var chart = d3.select("body")
    .append("svg:svg")
    .attr("class", "chart")
    .attr("width", 420)
    .attr("height", 20 * useData.length);
    

    您需要检查图表是否存在,如果存在,请不要调用该行。

    // outside of .onmessage
    var chart;
    
    // inside of .onmessage
    if (!chart) {
        chart = d3.select("body")
        .append("svg:svg")
        .attr("class", "chart")
        .attr("width", 420)
        .attr("height", 20 * useData.length);
    }
    

    【讨论】:

    • 感谢您的回复。我试过了,现在它只绘制一次图,但不会用新数据更新该图。
    • 也许是因为高度只会设置一次。可能需要在 if 语句之外执行chart.attr('height', 20 * useData.length)
    • 将 chart.attr('height', 20 * useData.length) 放在 if 语句之外现在不会打印任何图形。
    【解决方案2】:

    就像布赖恩说的,你会在每个 onmessage 事件中不断创建一个新的 svg 元素。但是,在 D3 中,您不需要使用 if 语句来检查元素是否存在;进行数据连接后,enter() 选择将仅包含尚不存在的元素:

    // data join
    var chart = d3.select("body").selectAll(".chart")
        .data([useData]); // if you wanted multiple charts: .data([useData1, useDate2, useData3])
    
    // enter
    chart.enter().append("svg") // this will only execute if the .chart did not exist yet
        .attr("class", "chart")
        .attr("width", 420);
    
    // update (both new and existing charts)
    chart
        .attr("height", function(d) { return 20 * d.length; });
    

    Thing with Joins 文章中解释了数据连接、enter()、update() 和 exit() 选择的概念。另请参阅 3 General Update Pattern 文章。

    当您在图表中更新或添加新的矩形元素时,您必须使用类似的方法。目前假设 useData 包含所有累积的数据(尽管 useData.length = 0 可能意味着情况并非如此):

    // data join
    var rects = chart.selectAll("rect")
        .data(function(d) { return d; }); // use the data bound to each chart
    
    // enter
    rects.enter().append("rect");
    
    // update
    rects
        .attr("y", function(d) { return y(d.yValue); }) // not sure what your data structure looks like
        .attr("width", function(d) { return x(d.xValue); })
        .attr("height", y.rangeBand());
    
    // exit
    rects.exit().remove();
    

    Path Transitions 中给出了一些如何使用实时数据更新路径的建议。

    【讨论】:

    • 谢谢你......当我运行它时,我在控制台日志中得到一个“ReferenceError: y is not defined”。正如您所说,您不知道我的数据结构是什么样的。很简单,useData 只是一个数字数组,例如:[1,2,3,5,8,13,21,34,55,89]。我将如何摆脱那个引用错误?
    • y 函数是您的序数比例...您有 jsfiddle 或可以分享的东西吗?图表部分,没有 websocket 的东西。
    • 查看mbostock.github.com/d3/tutorial/bar-2.html 如何创建适当的过渡等。也许这个例子就是你想要实现的?
    • 感谢 jsfiddle。本教程不是我想要的,因为我想在数据进入时在每个条形之上构建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多