我正在尝试为一些学生相关数据(下面的示例记录)创建数据可视化,但是当 d3 渲染它时,它会遍历数据两次并覆盖它,只在屏幕上留下第二次的结果。我在这里使用行计数器,这样我就有办法根据有多少个矩形来设置每个矩形的 y 坐标。我认为这在某种程度上让事情变得有点困惑。任何关于如何使数据不会被迭代两次的帮助将不胜感激。
另外,为了以防万一,这段代码位于 angular.js 指令中。
抱歉,如果我只是在这里做了一些非常愚蠢的事情
// student records sample...
var studentData = [
{
"studentID" : 1001,
"firstName" : "jill",
"lastName" : "smith",
"workLoadDifficulty" : 16,
"smileStartAngle" : -90,
"smileEndAngle" : 90,
},
{
"studentID" : 1008,
"firstName" : "bob",
"lastName" : "smith",
"workLoadDifficulty" : 99,
"smileStartAngle" : 90,
"smileEndAngle" : -90,
}
];
(function () {
'use strict';
angular.module('learnerApp.directives')
.directive('d3Bars', ['d3', function(d3) {
return {
restrict: 'EA',
scope: {
data: "=",
label: "@",
onClick: "&"
},
link: function(scope, iElement, iAttrs) {
var paddingForShape = 10;
var rowCounter = -1;
var height = 400;
var width = 300;
var svgContainer = d3.select(iElement[0])
.append("svg")
.attr("width", width)
.attr('height', height);
// on window resize, re-render d3 canvas
window.onresize = function() {
return scope.$apply();
};
scope.$watch(function(){
return angular.element(window)[0].innerWidth;
}, function(){
return scope.render(scope.data);
}
);
// watch for data changes and re-render
scope.$watch('studentData', function(newVals, oldVals) {
return scope.render(newVals);
}, true);
// define render function
scope.render = function(data){
// remove all previous items before render
svgContainer.selectAll("*").remove();
var workLoadColor = d3.scale.category10()
.domain([0,100])
.range(['#02FA28', '#73FA87', '#C0FAC9','#FAE4C0', '#FAC775', '#FAA823','#FA9A00','#FA8288', '#FC4750', '#FA0511' ])
var studentRects = svgContainer.selectAll('rect')
.data(studentData, function(d) {
console.log(d.studentID);
console.log('hello');
return "keyVal" + d.studentID;
})
.enter()
.append("rect");
var studentRectAttributes = studentRects
.attr("x", function(d,i) {
return ((i * 50) % width) + paddingForShape;
})
.attr("y", function(d,i) {
var value = ((i * 50) % width)
if (value === 0) {
rowCounter = rowCounter + 1;
}
var value = (rowCounter * 50);
console.log('Y Val: ', i);
console.log(value);
return value;
})
.attr("height", 30)
.attr("width", 40)
.style("fill", function(d) {
return workLoadColor(d.workLoadDifficulty)
});
};
}
};
}]);
}());
最佳答案
如果您执行数据连接两次,则需要指定 key
这样您就不会覆盖当前选择中的元素。您可能想要更改您的studentRects
定义为:
var studentRects = svgContainer.selectAll('rect')
.data(studentData, function(d) { return d.firstName + ' ' + d.lastName; });
studentRects.enter().append("rect");
参见selection.<a href="https://github.com/mbostock/d3/wiki/Selections#wiki-data" rel="noreferrer noopener nofollow"><strong>data</strong></a>([values[, key]])
If a key function is not specified, then the first datum in the specified array is assigned to the first element in the current selection, the second datum to the second selected element, and so on.
关于javascript - D3.js 复制我的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19626238/