2012-06-21 19 views
42

Estoy intentando crear mi primera aplicación con AngularJS. Se ve bien, pero hay mucha abstracción, y estoy curioso si alguien tiene consejos sobre la forma más idiomática de usar la metodología angular para actualizar visuales creados con d3js.D3 dentro de una aplicación AngularJS

Gracias, pb

Respuesta

34

Con el fin de hacer que los marcos angulares y otros juegan agradable es para envolver los "otros" marcos utilizando directivas.

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

Lo que desea hacer es decirle angular cuando los datos se ha actualizado por los "otros" marcos. Si angular no necesita saber, entonces su tarea es más simple.

Este es un ejemplo que funciona con SVG, es increíble

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

Este es un ejemplo que envuelve TinyMCE

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

44

Por favor, compruebe también el artículo de Brian Ford (Interno de AngularJS) donde describe la integración de AngluarJS con D3 en detalle.

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

+0

Esto es mucho más útil, gracias por compartir :) – gouravtiwari21

+1

Aquí encontrará otro artículo cómo integrar D3 en angular http://goo.gl/KYBFnX y un proyecto de GitHub Seed http://goo.gl/CS97f2 –

3

También existe la posibilidad de insertar los AngularJS manejan sintaxis bar directamente en el d3 generado elementos:

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' }"; 
           }); 

Tenga en cuenta las siguientes cosas: el alcance es en realidad el alcance angular objeto pasado de la directiva a la función de renderizado. Establecer el estilo de un elemento a una expresión "{{...}}" no funcionará, así que estoy usando el atributo "ng-style" aquí.

Sin embargo, hay un truco más: Es necesario contar angular para mirar a los elementos DOM generados dinámicamente y vinculante de alambre seguridad de los datos, que sé ahora de dos maneras de hacer esto:

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

la otra forma de hacerlo es la siguiente:

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

Ahora puede cambiar los miembros de su alcance y se actualizarán directamente a los elementos de d3, en este caso los círculos SVG. En el controlador angular (que se crea una instancia antes de los fuegos de la directiva que dibuja los objetos 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); 

Tenga en cuenta la llamada $ digest, que le dice a angular que digiera el alcance cambiado; esto cambiará los valores en los elementos del círculo svg. Para algo como animaciones y tal, d3 ya no es responsable y uno tendría que implementarlo manualmente o usar un patrón diferente.

0

También puede seguir con este tutorial/screencast para ver cómo usar D3 con angular. Es un poco diferente, ya que utiliza una biblioteca envoltorio alrededor d3 llamada carrito, que proporciona un poco de materia específica graficar, pero el enfoque es exactamente el mismo:

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

0

Si utilizamos d3 dentro de una directiva para generar elementos con otras directivas angulares (como creo que encontrará es un requisito bastante común) puede llamar al $compile al final de la fase de ACTUALIZACIÓN del proceso de representación con el método call(). Como esto (suponiendo que estamos haciendo un montón de círculos):

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