D3.js AngularJS应用程序中的D3

D3.js AngularJS应用程序中的D3,d3.js,angularjs,D3.js,Angularjs,我正在尝试用AngularJS创建我的第一个应用程序。它看起来很整洁,但有很多抽象,我只是好奇是否有人对使用角度方法更新使用d3js创建的视觉效果的最惯用方法有什么建议 谢谢, bp为了使angular和其他框架发挥作用,需要使用指令包装“其他”框架 您要做的事情是告诉angular“其他”框架何时更新了数据。如果angular不需要知道,那么您的任务就更简单了 下面是一个使用SVG的示例,它非常棒 下面是一个包装TinyMCE的示例 也可以将AngularJS handle bar语法直接

我正在尝试用AngularJS创建我的第一个应用程序。它看起来很整洁,但有很多抽象,我只是好奇是否有人对使用角度方法更新使用d3js创建的视觉效果的最惯用方法有什么建议

谢谢,
bp

为了使angular和其他框架发挥作用,需要使用指令包装“其他”框架

您要做的事情是告诉angular“其他”框架何时更新了数据。如果angular不需要知道,那么您的任务就更简单了

下面是一个使用SVG的示例,它非常棒

下面是一个包装TinyMCE的示例


也可以将AngularJS handle bar语法直接插入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' }";
                                });
请注意以下事项:范围实际上是从指令传递到渲染函数的角度范围对象。将元素的样式设置为“{…}}”表达式将不起作用,因此我在这里使用“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循环。在角度控制器中(在绘制d3对象的指令触发之前实例化)

$scope.circles=[];
对于(变量i=0;i<50;i++)
{
$scope.circles.push(new Circle());
}
setInterval(函数()
{
$scope.circles.forEach(函数(d,i){$scope.circles[i]=new Circle();});
$scope.$digest();
}, 2000);

请注意$digest调用,它告诉angular消化更改的范围;这将更改svg圆圈元素上的值。对于任何类似动画之类的东西,d3现在不再负责了,必须手动实现或使用不同的模式

您还可以按照本教程/屏幕广播了解如何将D3与angular一起使用。 这有点不同,因为它利用了d3的包装器库,称为rickshaw,它提供了一些特定于图形的东西,但方法完全相同:


如果我们在指令中使用d3来生成具有其他角度指令的元素(我认为这是一个非常常见的要求),那么在渲染过程的更新阶段结束时,可以使用
调用()
方法调用
$compile
。像这样(假设我们正在渲染一组圆):

    $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);
mySvg.selectAll("circle")
                .data(scope.nodes)
                .enter()
                .append("circle")
                .attr("someDirective")
                .call(function(){
                    $compile(this[0].parentNode)(scope);
                });