Подтвердить что ты не робот

D3 в приложении AngularJS

Я пытаюсь создать свое первое приложение с помощью AngularJS. Это выглядит аккуратно, но там много абстракции, и мне просто интересно, есть ли у кого-нибудь советы по самому идиоматическому способу использования методологии angular для обновления визуальных образов, созданных с помощью d3js.

Спасибо, п.н.

4b9b3361

Ответ 1

Чтобы сделать angular и другие фреймворки хорошими, нужно обернуть "другие" фреймворки с помощью директив.

http://docs.angularjs.org/guide/directive

То, что вы хотите сделать, это сообщить angular, когда данные были обновлены "другими" фреймами. Если angular не нужно знать, тогда ваша задача будет проще.

Вот пример, который работает с SVG, его удивительным

http://sullerandras.github.com/SVG-Sequence-Diagram/

Вот пример, который включает TinyMCE

http://jsfiddle.net/programmieraffe/kjsEV/

Ответ 2

Пожалуйста, также просмотрите статью Брайана Форда (интернатура AngularJS), где он подробно описывает интеграцию AngluarJS с D3.

http://briantford.com/blog/angular-d3.html

Ответ 3

Существует также возможность вставить синтаксис дескриптора AngularJS непосредственно в создаваемые d3 элементы:

var containerDiv = d3.select(targetCSSSelectorForADiv);
var svgG = containerDiv
                                .append("svg")
                                .attr("width", width + margin.left + margin.right)
                                .attr("height", height + margin.top + margin.bottom)
                                .append("g")
                                .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

 svgG.selectAll(".tempclass").data(scope.circles).enter()
                                .append("circle")
                                .attr("class", "tempclass")
                                .attr("cx", function (d, i) { return "{{circles[" + i + "].cx}}" })
                                .attr("cy", function (d, i) { return "{{circles[" + i + "].cy}}" })
                                .attr("r", function (d, i) { return "{{circles[" + i + "].radius}}" })
                                .attr("ng-style", function (d, i)
                                {
                                    return "{fill: circles[" + i + "].circolor"
                                        + ", opacity: circles[" + i + "].opa"
                                        + ", 'stroke-width': 4*circles[" + i + "].opa"
                                        + ", stroke: 'red' }";
                                });

Обратите внимание на следующее: область действия - это объект объекта angular, переданный из директивы в функцию рендеринга. Установка стиля элемента в выражение "{...}} не будет работать, поэтому я использую здесь атрибут" ng-style ".

Однако есть еще один трюк: вам нужно сказать angular посмотреть на динамически сгенерированные элементы DOM и связать привязку данных, теперь я знаю два способа сделать это:

//the target div is the one with the angular ng-controller attribute 
//this you can call at the end of the d3 rendering call from within the render function
angular.bootstrap(document.getElementById("d3ContainerDivID"), ['d3App']);

Другой способ:

//and this could be called from the directive that triggered the rendering or
//some other place that could have the angular $compile service injected
$compile(document.getElementById("d3ContainerDivID"))(scope);

Теперь вы можете изменить свои члены области действия, и они будут напрямую обновлены до ваших элементов d3, в этом случае круги svg. В контроллере angular (который получает экземпляр перед срабатыванием директивы, который рисует объекты d3).

    $scope.circles = [];
    for (var i = 0; i < 50; i++)
    {
        $scope.circles.push(new Circle());
    }
    setInterval(function ()
    {
        $scope.circles.forEach(function (d, i) { $scope.circles[i] = new Circle(); });
        $scope.$digest();
    }, 2000);

Обратите внимание на вызов $digest, который сообщает angular переварить измененную область; это изменит значения для элементов круга SVG. Для чего-то вроде анимации и т.д. Теперь d3 теперь не отвечает, и нужно будет вручную или использовать другой шаблон.

Ответ 4

Вы также можете следовать этому руководству /screencast, чтобы узнать, как использовать D3 с помощью angular. Это немного отличается, потому что в нем используется библиотека-оболочка вокруг d3, называемая rickshaw, которая предоставляет некоторые графические данные, но подход точно такой же:

http://tagtree.tv/d3-with-rickshaw-and-angular

Ответ 5

Если мы используем d3 внутри директивы для генерации элементов с другими директивами Angular (как я думаю, вы найдете это довольно общее требование), вы можете вызвать $compile в конце фазы UPDATE процесса рендеринга с помощью метод call(). Подобно этому (если мы создаем кучу кругов):

mySvg.selectAll("circle")
                .data(scope.nodes)
                .enter()
                .append("circle")
                .attr("someDirective")
                .call(function(){
                    $compile(this[0].parentNode)(scope);
                });