Нарисуйте произвольное количество линий на графике протоисов

Моя цель

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

Что я сделал

Я сделал jsfiddle, показывающий, как я могу добавить фиксированное количество линий в график, а также воспроизвел этот код ниже. Здесь я добавил 2 строки путем явного кодирования x_value0 а также x_value1, В коде есть две части кода Protovis, которые имеют отношение, которые я пометил Section A а также Section B, Section A является функцией protovis, которая определяет, где будет проведена линия, и 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 в виде массива, и цикл по этому. Я на полпути в моей попытке. Я сделал второй 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]);
    })
}

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

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

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

Редактировать - больше прогресса

Я, кажется, стал ближе к тому, что я хочу, устраняя Section A и перемещая эту функцию внутри Section B, Смотрите мой последний 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 массив и перезаписать все предыдущие. Есть идеи?

1 ответ

Решение

Замените ваш цикл следующим кодом

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/

Другие вопросы по тегам