Карта дерева Protovis - показывать метки при наведении курсора - PullRequest
0 голосов
/ 21 сентября 2011

У меня есть древовидная карта, которую я создал.Теперь я пытаюсь заставить зависание работать правильно.Я хотел бы, чтобы текст для каждого treemap.leaf появлялся только тогда, когда пользователь наводит курсор на этот конкретный лист.

Я пытался следовать этому примеру, но безрезультатно http://mbostock.github.com/protovis/docs/interaction.html

У меня есть следующий код:

var json = {
    "sectors":{
        "electronics": { "Sony": 85, "AMD": 70, "Techtronics": 20, "Apple": 220, "Microsoft": 340},
        "automotive": {"Chevy": 43, "Audi":120, "BMW": 200}},
    "ids":{"Sony":72833,"AMD":582926,"Techtronics":839261, "Apple":822463, "Microsoft":242512, "Chevy":627363, "Audi":524362,"BMW":25143}   
};

var tree = json.sectors;
var ids = json.ids;

var nodes = pv.dom(tree).root("tree").nodes();
color = pv.Colors.category10().by(function(d){return  d.parentNode.nodeName});

var vis = new pv.Panel()
 .width(400)
 .height(400)
 .canvas("test");
var treemap = vis.add(pv.Layout.Treemap)
 .nodes(nodes)
 .round(true);  

treemap.leaf.add(pv.Panel)
 .def("active", false)
 .fillStyle(function(d) d.active ? "lightcoral" : color(d))
 .strokeStyle("#fff")
 .lineWidth(1)
 .antialias(false)
 .cursor("pointer")
 .event("mouseover", function(d) { return this.active(true)});

treemap.label.add(pv.Label)
 .visible(function() {return this.parent.children[0].active()})
 .textStyle(function(d) {return pv.rgb(0, 0, 0, 1)});

vis.render();

1 Ответ

1 голос
/ 26 сентября 2011

Здесь есть несколько проблем:

  • Когда вы используете метод .event(), и функция, которую вы передаете, возвращает экземпляр pv.Mark, Protovis переопределяет марку и ее детей.(Документация довольно непрозрачна в отношении требования о том, чтобы вы возвращали метку, которую хотите перерисовать.)

  • В макете Treemap метки не дочерниеузлов - это отдельная группа дочерних элементов макета.Поэтому, когда вы обновляете узел, вы не получите соответствующий ярлык для повторного рендеринга.

  • У вас есть опечатка в строке:

    .fillStyle(function(d) d.active ? "lightcoral" : color(d))
    

    d это данные, а не экземпляр.Это должно быть:

    .fillStyle(function() this.active() ? "lightcoral" : color(d))
    

    Но, как отмечено выше, это все равно не обновит метку (и хотя я не слишком много играл с этим, просто исправление этой строки, кажется, выделяет все узлыа не только тот, на котором вы закончили).

Таким образом, чтобы исправить все это, вы должны установить active def на treemap, а не на узле.Вместо того, чтобы просто использовать true / false, вы можете установить индекс активного узла, а затем использовать тот же индекс для ссылки на метку:

var treemap = vis.add(pv.Layout.Treemap)
 .nodes(nodes)
 .round(true)
 // define the active node on the layout
 .def("active", -1);  

treemap.leaf.add(pv.Panel)
 .fillStyle(function(d) { 
     return treemap.active() == this.index ? "lightcoral" : color(d) 
 })
 // ...
 .event("mouseover", function() { 
     return treemap.active(this.index);
 })
 .event("mouseout", function() { 
     return treemap.active(-1);
 });

treemap.label.add(pv.Label)
 .visible(function() {
     return treemap.active() == this.index;
 });

Работая здесь jsFiddle.

Недостатком является то, что вы каждый раз перерисовываете всю карту дерева.Я думаю, что, вероятно, есть способ перерисовать только конкретный узел и метку, но это было бы более сложно, поэтому, если производительность не кажется проблемой, я бы не стал беспокоиться.

...