![](/img/trans.png)
[英]d3js angular directive for area chart using d3.mouse event for tooltip
[英]How to integrate `d3js` graph with angular directive
我正在嘗試將d3js
圖形與我的angular指令集成在一起。 但我沒有得到預期的結果。
undefined%
標簽 li
)時,不是更新圖形,而是附加一個新圖形。 請單擊頂部的列表。
這是我的代碼和演示:
var myApp = angular.module("myApp", ['ngResource']);
myApp.factory("server", function($resource) {
return $resource('https://tcp.firebaseio.com/graph.json')
})
myApp.controller("main", function($scope, server) {
$scope.test = "Hellow";
$scope.data = server.query();
$scope.data.$promise.then(function(result) {
$scope.values = result;
$scope.defaultValue = $scope.values[0].value;
console.log($scope.defaultValue);
})
$scope.updateGraph = function(item) {
$scope.defaultValue = item.value;
}
});
var planVsActual = function($timeout) {
return {
replace: true,
template: "<div id='pieGraph'></div>",
link: function(scope, element, attr) {
$timeout(function() {
scope.$watch("defaultValue", function(newVal, oldVal) {
var phraseValue = [newVal, 100 - newVal];
drawPie(phraseValue);
function drawPie(array) {
console.log(element.width)
var width = element.width(), height = element.height(),
radius = Math.min(width, height) / 1.2, data = array;
if (!array.length) return;
var color = d3.scale.ordinal()
.domain(array)
.range(["#ffff00", "#1ebfc5"]);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d });
var arc = d3.svg.arc()
.outerRadius(radius - 90)
.innerRadius(radius - 85);
var svg = d3.select("#pieGraph")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var g = svg.selectAll(".arc")
.data(pie(array))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d,i) { return color(d.data); });
g.append("text")
.text(array[0]+'%')
.attr("class", "designVal")
.style("text-anchor", "middle")
}
})
}, 100)
}
}
}
angular.module("myApp")
.directive("planVsActual", planVsActual);
您每次都會附加一個新的svg。
簡單的解決方法是先清空容器:
scope.$watch("defaultValue", function(newVal, oldVal) {
// empty the chart element
element.html('');
// chart code
});
我確定您可以存儲對所創建的初始對象的引用,而不是每次都創建一個新對象,這將使您可以對差異進行動畫處理,但是出於此答案的目的,我無意重寫您的d3代碼,而只是提供解決方案符合您當前的工作
在Angular上使用d3制作動態圖表時,最佳做法是將圖表數據綁定到指令。
<plan-vs-actual data="defaultValue"></plan-vs-actual>
在JavaScript中,您必須將scope: {data: '='}
到指令定義對象。
return {
replace: true,
template: <div id="pieGraph></div>,
scope: {data: '='},
link: function(){
//link
}
};
此外,您希望在加載任何數據之前在鏈接函數中定義盡可能多的d3可視化效果,以實現最佳性能。 盡快加載不依賴數據的圖形部分。 在您的情況下,這意味着變量width ... height ... radius ... color.range()... pie ... arc ... svg ...都可以在范圍之外定義。 ,然后再加載任何數據。 您的鏈接如下所示:
link: function(scope,element,attr){
$timeout(function(){
var width = element.width(),
height = element.height(),
radius = Math.min(width, height) / 1.2;
var color = d3.scale.ordinal()
.range(["#ffff00", "#1ebfc5"]);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d });
var arc = d3.svg.arc()
.outerRadius(radius - 90)
.innerRadius(radius - 85);
var svg = d3.select("#pieGraph")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
//scope.$watch goes here
},100)
}
由於您現在正在使用最佳實踐,因此scope.$watch
函數現在將監視指令的data
屬性,而不是defaultValue
,它看起來像這樣。
scope.$watch('data',function(newVal, oldVal){
//code here
})
現在我們必須弄清楚scope.$watch
...中發生的最重要的變化是我們打破了.data()和.enter()方法。 下面我向您展示新的scope.$watch
外觀,並帶有內聯注釋對其進行解釋。
scope.$watch("data", function(newVal, oldVal) {
var phraseValue = [newVal, 100 - newVal];
drawPie(phraseValue);
function drawPie(array) {
console.log(element.width)
var data = array;
if (!array.length) return;
color.domain(array);
//NOTICE BELOW how we select the data and then chain .enter() separately,
//doing that allows us to use D3's enter(), exit(), update pattern
//select all .arc from SVG and bind to data
var g = svg.selectAll(".arc")
.data(pie(array));
//select all <text> from SVG and bind to data as well
var t = svg.selectAll('text').data(array);
//enter
g.enter()
.append("path")
.attr("class", "arc")
.attr("d", arc)
.style("fill", function(d,i) { return color(d.data); });
t.enter()
.append('text')
.text(array[0]+"%")
.attr("class", "designVal")
.style("text-anchor", "middle");
//exit
//in this example exit() is wholly unnecessary since the # of datum
//will never decrease. However, if it would, this would account for it.
g.exit().remove();
t.exit().remove();
//update
//update the 'd' attribute of arc and update the text of the text
g.attr('d',arc);
t.text(array[0]+'%');
}
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.