42 votes

D3 dans une application AngularJS

J'essaie de créer ma première application avec AngularJS. Elle a l'air bien, mais il y a beaucoup d'abstraction, et je suis juste curieux si quelqu'un a des conseils sur la façon la plus idiomatique d'utiliser la méthodologie angulaire pour mettre à jour les visuels créés avec d3js.

Merci, bp

40voto

Brad Green Points 1046

Veuillez également consulter l'article de Brian Ford (stagiaire AngularJS) où il décrit en détail l'intégration d'AngluarJS avec D3.

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

34voto

Dan Doyon Points 4081

Pour faire en sorte qu'angular et les autres frameworks soient compatibles, il faut envelopper les "autres" frameworks à l'aide de directives.

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

La chose que vous voulez faire est de dire à angular quand les données ont été mises à jour par les "autres" frameworks. Si angular n'a pas besoin de savoir, alors votre tâche est plus simple.

Voici un exemple qui fonctionne avec SVG, c'est génial.

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

Voici un exemple qui englobe TinyMCE

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

3voto

hans Points 374

Il est également possible d'insérer la syntaxe de la barre de poignée AngularJS directement dans les éléments générés par 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' }";
                                });

Veuillez noter les points suivants : le scope est en fait l'objet angular scope transmis par la directive à la fonction de rendu. Définir le style d'un élément avec une expression "{{...}}" ne fonctionnera pas. J'utilise donc l'attribut "ng-style" ici.

Cependant, il y a une autre astuce : vous devez dire à Angular de regarder les éléments DOM générés dynamiquement et d'établir la liaison des données, je connais maintenant deux façons de le faire :

//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']);

l'autre voie est la suivante :

//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);

Vous pouvez maintenant modifier les membres de votre portée et ils seront directement mis à jour dans vos éléments d3, dans ce cas les cercles svg. Dans le contrôleur angulaire (qui est instancié avant le déclenchement de la directive qui dessine les objets 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);

Veuillez noter l'appel $digest, qui indique à angular de digérer la portée modifiée ; cela changera les valeurs des éléments du cercle svg. Pour tout ce qui concerne les animations et autres, d3 n'est plus responsable et il faut l'implémenter manuellement ou utiliser un autre modèle.

0voto

hendrikswan Points 568

Vous pouvez également suivre ce tutoriel/casting pour voir comment utiliser D3 avec angular. C'est un peu différent, car il utilise une bibliothèque enveloppante autour de D3, appelée rickshaw, qui fournit des fonctionnalités spécifiques aux graphiques, mais l'approche est exactement la même :

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

0voto

david004 Points 1310

Si nous utilisons d3 à l'intérieur d'une directive pour générer des éléments avec d'autres directives Angular (comme je pense que vous trouverez que c'est une exigence assez commune), vous pouvez appeler $compile à la fin de la phase d'UPDATE du processus de rendu avec le call() méthode. Comme ceci (en supposant que nous effectuons le rendu d'un groupe de cercles) :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X