我正在尝试在我的d3可视化中使用angularjs 工具提示指令,所以我有类似的东西
var node = svg.selectAll(".node") .data(nodes) .enter().append("circle") .attr("tooltip-append-to-body", true) .attr("tooltip", function(d) { return d.name; }) // ... attributes
但是,工具提示未显示.我需要$compile
什么?我也试过把它包裹起来$timeout
,但那不起作用.
我有类似的问题,是的,解决了它$compile
.我假设您的d3代码在自定义指令中.从那里你可以添加你的工具提示属性,删除你的自定义指令属性,所以$ compile只运行一次,并调用$ compile:
myApp.directive('myNodes', ['$compile', function ($compile) { return { restrict: 'A', link: function(scope, element, attrs) { var nodes = [{"name": "foo"}, {"name": "bar"}] var mySvg = d3.select(element[0]) .append("svg") .attr("width", 100) .attr("height", 100); var node = mySvg.selectAll(".node") .data(nodes) .enter() .append("circle") .attr("cx", function(d,i){ return 20+i*50; }) .attr("cy", 50) .attr("r", 10) .attr("tooltip-append-to-body", true) .attr("tooltip", function(d){ return d.name; }); element.removeAttr("my-nodes"); $compile(element)(scope); } }; }]);
$ compile服务确保使用指令添加的属性编译元素.
这是使用上述代码的工作小提琴.希望这是你正在寻找的!
来自@jbll的一个非常好的答案 - 但最好将指令编译链接到输入阶段的结尾.具有输入阶段和更新阶段非常重要,因此图形可以响应数据更新而无需重新创建每个元素.无论何时更改模型,上一个答案都会在每个节点上编译每个指令.这可能是想要的,但可能不是.
以下代码显示$ scope.nodes变量更改时的d3图形更新.
这也有点整洁,因为它不需要删除和重新创建原始指令,这看起来有点像黑客.
这是小提琴
将按钮添加到html:
<button ng-click="moveDots()">Move the dots</button>
然后将JavaScript fie更改为:
var myApp = angular.module('myApp', ['ui.bootstrap']); myApp.controller('myCtrl', ['$scope', function($scope){ $scope.nodes = [ {"name": "foo", x: 50, y: 50}, {"name": "bar", x: 100, y: 100} ]; $scope.moveDots = function(){ for(var n = 0; n < $scope.nodes.length; n++){ var node = $scope.nodes[n]; node.x = Math.random() * 200 + 20; node.y = Math.random() * 200 + 20; } } }]); myApp.directive('myNodes', ['$compile', function ($compile) { return { restrict: 'A', link: function(scope, element, attrs) { var mySvg = d3.select(element[0]) .append("svg") .attr("width", 250) .attr("height", 250); renderDots(); scope.$watch("nodes", renderDots, true); function renderDots(){ // ENTER PHASE mySvg.selectAll("circle") .data(scope.nodes) .enter() .append("circle") .attr("tooltip-append-to-body", true) .attr("tooltip", function(d){ return d.name; }) .call(function(){ $compile(this[0].parentNode)(scope); }); // UPDATE PHASE - no call to enter(nodes) so all circles are selected mySvg.selectAll("circle") .attr("cx", function(d,i){ return d.x; }) .attr("cy", function(d,i){ return d.y; }) .attr("r", 10); // todo: EXIT PHASE (remove any elements with deleted data) } } }; }]);