使用Protovis的交互式区域图表

dan*_*ani 4 javascript json visualization protovis

这对Protovis新人来说是一个相当艰巨的项目,但也许你可以帮助我把它分成易消化的块?

我想要构建的是一个"交互式区域图表",如下所示: http://i.stack.imgur.com/7bs9W.png

首先,它是数据......我在Excel中有各省的数据:

Province   Year  10  100  1000  10000 
A          1970  2   4    6     3 
A          1971  3   6    8     5 
B          1970  6   9    12    6 
B          1971  4   8    11    8 
....       ...   .   .    .     .

对于每个省和年,我希望能够绘制面积图:

vis.add(pv.Area) 
    .data(data.ProvinceA[1970]) 
    .bottom(1) 
    .interpolate("basis") 
    .left(function(d) x(d.x)) 
    .height(function(d) y(d.y)) 
    .fillStyle("rgb(21,173,210)") 
    .anchor("top").add(pv.Line) 
    .lineWidth(3); 
Run Code Online (Sandbox Code Playgroud)

然后我想添加两种类型的交互:

  1. 省的选择
  2. 时间滑块

选择复选框和时间滑块一起确定在任何给定时间可见的区域.例如,如果选择了省A并且年份是1984年,则仅显示该区域.如果现在拖动时间滑块,则现在会显示省A的相应年份.如果选中了另一个省,则会覆盖这些区域,并在时间滑块移动时重新绘制这两个区域.

Protovis问题:

  1. 如何格式化此应用程序的数据(省,年,年,年)?
  2. 如何实现复选框与区域的绑定?
  3. 如何实现时间滑块?在Protovis中,或者像是一个带有侦听器的外部组件,触发器重新渲染图形?

nra*_*itz 6

格式化数据:第一步是使用一些外部工具将它变成JSON(我真的很喜欢Google Refine,虽然这是一个非常大的工具,如果这就是你所需要的 - 试试数据转换器的快速和肮脏的选择).这些工具可能会将数据作为JSON对象提供给您,如下所示:

`[{"Province":"A", "Year":"1970", "10":2, "100":4, "1000":6, "10000":3}, ...]`
Run Code Online (Sandbox Code Playgroud)

一旦您将数据作为JSON提供,您就会希望将其变为可见的形状.你想要传递每个pv.Area一个值数组 - 从你的描述看起来你想要[10,100,1000,10000]值.Protovis有很多用于操作数据的工具 - 请参阅pv.Nest运算符.有很多方法可以解决这个问题 - 我可能会这样做:

data = pv.nest(data)
    .key(function(x) {return x.Province})
    .key(function(x) {return x.Year})
    .rollup(function(v) {
        return [v[0]['10'], v[0]['100'], v[0]['1000'], v[0]['10000']];
    });
Run Code Online (Sandbox Code Playgroud)

它给你一个像这样的对象:

{ 
    A: {
        1970: [2,4,6,3]
        // ...
    },
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这为您设置了界面元素.将已检查的省份数组和当前年份保存在全局变量中:

var currentProvinces = ['A', 'B', ...];
var currentYear = 1970;
Run Code Online (Sandbox Code Playgroud)

并设置您的区域以引用这些变量:

// a containing panel to help with layout and data
var panel = vis.add(pv.Panel)
    .data(function() currentProvinces); // making this a function allows it to 
                                        // be re-evaluated later
// the area itself
var area = panel.add(pv.Area)
    .data(function(province) data[province][currentYear]);
    // plus more area settings as needed
Run Code Online (Sandbox Code Playgroud)

现在使用一些其他库 - 我偏向于jQuery,使用滑块的jQuery UI - 来创建你的界面元素.每个元素的onchange函数只需要设置相应的全局变量并调用vis.render()(假设调用了根面板vis).这应该非常简单 - 请参阅这里的Protovis示例,使用jQuery UI使时间滑块非常类似于您的想法.