1

Мои цели

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

Что я сделал

Я сделал jsfiddle, показывающий, как я могу добавить определенное количество строк графа, а также воспроизводил этот код, приведенный ниже. Здесь я добавил 2 строки, явно кодируя x_value0 и x_value1. В коде есть два фрагмента кода протовиса, которые имеют значение, которые я обозначил Section A и Section B. Section A - это функция протовиса, которая определяет, где будет нарисована линия, и Section B вызывает эти функции.

// X intercept values hard coded 
var x_value0 = 30; 
var x_value1 = 70; 

new pvc.MetricDotChart({ 
    canvas: "cccExample", 
    width: 500, 
    height: 400, 
    axisGrid: true, 
    axisZeroLine: false, 
    selectable: true, 

    extensionPoints: { 

     plot_add: function() { 
      var panel = new pv.Panel() 
       // Quadrant rules above grid, but below dots. 
       .zOrder(-1) 

       //// 
       // Section A Begin 
       //// 

       // Line 1 
       .def('l0', function() { 
        var ccc = this.getContext(); 
        var scale = ccc.chart.axes.base.scale; 
        var li = ccc.panel._layoutInfo; 
        return li.paddings.left + scale(x_value0); 
       }) 

       // Line 2 
       .def('l1', function() { 
        var ccc = this.getContext(); 
        var scale = ccc.chart.axes.base.scale; 
        var li = ccc.panel._layoutInfo; 
        return li.paddings.left + scale(x_value1); 
       }) 

       //// 
       // Section A End 
       //// 

      ; 

     //// 
     // Section B Begin 
     //// 

     // Line 1 
      panel 
      .add(pv.Rule) 
      .top(0) 
      .left (function() { return this.parent.l0();  }) 
      .height(function() { return this.parent.height(); }) 
      .width(null) 
      ;  

     // Line 2 
      panel 
      .add(pv.Rule) 
      .top(0) 
      .left (function() { return this.parent.l1();  }) 
      .height(function() { return this.parent.height(); }) 
      .width(null) 
      ;    

     //// 
     // Section B End 
     ////    

      return panel;  

     } 
    } 
}) 

.setData(testLDot2) 
.render(); 

То, что я хотел бы сделать вместо этого определить xvalues как массив, и петля над этим. Я немного наполовину в своей попытке. Я сделал second jsfiddle, где я пытаюсь переместить xvalues в массив. Проблема в том, что я не могу, похоже, успешно обернуть соответствующую часть в цикл for. Код из этого jsfiddle является:

// X intercept values in an array 
var x_values = [30, 60]; 

new pvc.MetricDotChart({ 
    canvas: "cccExample", 
    width: 500, 
    height: 400, 
    axisGrid: true, 
    axisZeroLine: false, 
    selectable: true, 

    extensionPoints: { 

     plot_add: function() { 
      var panel = new pv.Panel() 
       // Quadrant rules above grid, but below dots. 
       .zOrder(-1) 

       //// 
       // Section A Begin - How can I put this inside of a loop? 
       //// 

       // Line 1 
       .def('l0', function() { 
        var ccc = this.getContext(); 
        var scale = ccc.chart.axes.base.scale; 
        var li = ccc.panel._layoutInfo; 
        return li.paddings.left + scale(x_values[0]); 
       }) 

       // Line 2 
       .def('l1', function() { 
        var ccc = this.getContext(); 
        var scale = ccc.chart.axes.base.scale; 
        var li = ccc.panel._layoutInfo; 
        return li.paddings.left + scale(x_values[1]); 
       }) 

       //// 
       // Section A End 
       //// 

      ; 

     //// 
     // Section B Begin - I'm able to successfully loop this part 
     //// 

      for (i = 0; i < x_values.length; i++) { 
       // The name of the .def function defined above 
       var fn_name = 'this.parent.l' + i + '()'; 
       // Draw the lines 
        panel 
        .add(pv.Rule) 
        .top(0) 
        .left (function() { return eval(fn_name);  }) 
        .height(function() { return this.parent.height(); }) 
        .width(null) 
;  

      } 

     //// 
     // Section B End 
     ////    

      return panel;  

     } 
    } 
}) 

.setData(testLDot2) 
.render(); 

Я могу обернуть Section B внутри для цикла, и я хотел бы сделать что-то подобное для Section A:

for (i = 0; i < x_values.length; i++) { 
    .def('l'+i, function() { 
     var ccc = this.getContext(); 
     var scale = ccc.chart.axes.base.scale; 
     var li = ccc.panel._layoutInfo; 
     return li.paddings.left + scale(x_values[i]); 
    }) 
} 

или что-то подобное , Но проблема в том, что протовиз, похоже, не позволяет мне помещать код вокруг этого блока .def.

Я также попытался генерировать строку для каждого элемента в x_values массив, который содержит определение функции Section A, а затем вызвать его внутри кода protovis с помощью eval(), но это не работает до сих пор.

Любая помощь здесь была бы принята с благодарностью!

Edit - больше прогресса

я, кажется, получили ближе к тому, что я хочу, устраняя Section A и перемещение этой функции внутри Section B. См. my latest jsfiddle для этого кода. Ранее в Section B линия .left называлась одной из функций, определенных в Section A. Вместо этого я переехал определение этой функции в внутри .left строки кода, например, так:

//// 
// Section B Begin 
//// 

for (var i = 0; i < x_values.length; i++) { 
    var x = x_values[i]; 
    // Lines 
    panel 
    .add(pv.Rule) 
    .top(0) 
    .left (function() {     
     var ccc = this.parent.getContext(); 
     var scale = ccc.chart.axes.base.scale; 
     var li = ccc.panel._layoutInfo; 
     return li.paddings.left + scale(x);          
    }) 
    .height(function() { return this.parent.height(); }) 
    .width(null) 
    ;  
} 

Это работает сейчас, но до сих пор не совсем прав: это только рисунок последнюю строку в x_values массива и перезаписывать все предыдущие из них. Есть идеи?

ответ

3

Замените петлю следующим кодом

panel 
    .add(pv.Rule) 
    .data(x_values) 
    .top(0) 
    .left (
     function(d) {     
     this.index * 20 + 15 
     var ccc = this.parent.getContext(); 
     var scale = ccc.chart.axes.base.scale; 
     var li = ccc.panel._layoutInfo; 
     return li.paddings.left + scale(d);          
    }) 
    .height(function() { return this.parent.height(); }) 
    .width(null) 
    ;  

Скрипки http://jsfiddle.net/f9uhzaz9/

+0

Удивительное - спасибо! – Steve