开发者

more than one set of labels in protovis?

开发者 https://www.devze.com 2023-03-19 12:30 出处:网络
I\'d like to have both the values and the data categories on a graph.This is a bar chart and I\'d like to have the data values and a string开发者_JAVA技巧 printed in columns off to the left of the bar

I'd like to have both the values and the data categories on a graph. This is a bar chart and I'd like to have the data values and a string开发者_JAVA技巧 printed in columns off to the left of the bar:

A 1 #
B 3 ###

I tried chaining a two add(pv.Label) calls onto my graph, but it seems to do nothing - the second label set is not added. Is this something that can even be done with protovis? any advice?

vis = new pv.Panel()
.def("j", -1)
.width(800)
.height(50)
.right(3);

vis.add(pv.Bar)
.data(wData)
.bottom(0)
.width(20)
.height(function(d) d[1] * 1.2)
.left(function() this.index * 27)
.fillStyle(function() vis.j() == this.index ? "orange" : "steelblue")
.add(pv.Label)  **// does nothing!!**
.bottom(0)
.textAlign("center")
.textStyle("white")
.text(function(d) d[0] )
.event("mouseover", function() vis.j(this.index))
.event("mouseout", function() vis.j(-1))
.anchor("top").add(pv.Label)
.visible(function() vis.j() >= 0)
.textStyle("white")
.text(function(d) d[1]);
vis.render();


I actually did see both labels when I tried this out. But there are a couple of things that could be fixed here. The key point is that when you're chaining methods like this, when you add() a new mark, you change the context of the following method calls, e.g.:

vis.add(pv.Bar)
    // this applies to the Bar
    .width(10)
  .add(pv.Label)
    // this applies to the label
    .top(5);

There are a couple issues with this in your code:

  • Your event() handlers are attached to the Label, not to the Bar - unfortunately, Labels can't receive events in Protovis.

  • Your second Label is attached to the first Label. While this actually seems to work somewhat, it's better to avoid it - you really want it attached to the Bar.

The easy way to deal with this is to only chain methods on a single mark. You can do this by assigning the parent mark to a variable, then using that variable several times for different child marks. You also have you first Label attached directly to the Bar, and not to an anchor - attaching it to an anchor will usually give you more predictable results.

Updated code:

// make a new variable to refer to the bars
var bars = vis.add(pv.Bar)
    .data(wData)
    .bottom(0)
    .width(20)
    .height(function(d) d[1] * 1.2)
    .left(function() this.index * 27)
    .fillStyle(function() vis.j() == this.index ? "orange" : "steelblue")
    // you need to move the events up to apply 
    // to the bar - labels can't receive events, 
    // and the index will always be 0
    .event("mouseover", function() vis.j(this.index))
    .event("mouseout", function() vis.j(-1));

// now add each label to the bars
bars.anchor('bottom').add(pv.Label)
    .bottom(0)
    .textAlign("center")
    .textStyle("white")
    .text(function(d) d[0] );

// and again
bars.anchor("top").add(pv.Label)
    .visible(function() vis.j() >= 0)
    .textStyle("white")
    .text(function(d) d[1]);

There's a working version here: http://jsfiddle.net/nrabinowitz/ABmuq/

0

精彩评论

暂无评论...
验证码 换一张
取 消