prodio
Version:
Simplified project management
317 lines (279 loc) • 8.1 kB
JavaScript
var Scatter = module.exports = function(){
var
margin = {top: 20, left: 50, bottom: 20, right: 20},
width = -1,
height = 500,
duration = 500,
showXAxis = true,
showYAxis = true,
identity = '_id',
idx = 1,
style = false,
onUpdate = false,
getColor = false,
getX = function x(d){
return d.x;
},
getY = function y(d){
return d.y;
},
getR = function(d){
return 8;
},
getScaleX = function(data, w){
var min = d3.min(data, getX), max = d3.max(data, getX);
var r = ((max - min) * 0.1) || 1;
min -= r;
max += r;
return d3.scale.linear()
.domain([min, max])
.range([0, w])
;
},
getScaleY = function(data, h){
var min = d3.min(data, getY), max = d3.max(data, getY);
var r = ((max - min) * 0.1) || 1;
min -= r;
max += r;
return d3.scale.linear()
.domain([max, min])
.range([0,h])
;
},
getColor = function(d){
return 'black';
},
getText = function(d){ return d.text||''; },
enterNode = function(node){
var circle = node.append('svg:circle')
.attr('r', 1e-6);
if(getColor){
circle.style('fill', getColor);
}
node.append('svg:text')
.attr('text-anchor', 'middle')
.attr('dy', function(d){return -getR(d)-3})
.text(getText)
.style('fill-opacity', 1);
},
updateNode = function(node){
node.select('text')
.text(getText);
node.select('circle')
.attr('r', getR);
},
exitNode = function(node){
node.select('circle')
.attr('r', 1e-6);
node.select('text')
.style('fill-opacity', 1e-6);
}
;
var chart = function(selection){
selection.each(function(data){
var wid = width===-1?this.offsetWidth:width;
var w = wid - margin.left - margin.right;
var h = height - margin.top - margin.bottom;
var vis = d3.select(this).select('svg');
var x = getScaleX(data, w);
var y = getScaleY(data, h);
if(showXAxis){
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
;
}
if(showYAxis){
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
;
}
if(!vis[0][0]){
vis = d3.select(this).append('svg');
}
vis
.attr('width', wid)
.attr('height', height)
;
var node = vis.selectAll('g.node')
.data(data, function(d) { return d[identity] || (d[identity] = ++idx); })
;
var nodeEnter = node.enter().append('svg:g')
.attr('class', 'node')
.attr('transform', function(d, i) {
return 'translate(' + (x(getX(d, i)) + margin.left) + ',' + (margin.top+h) + ')';
})
;
enterNode(nodeEnter);
var nodeUpdate = node.transition()
.duration(duration)
.attr('transform', function(d, i) { return 'translate(' + (x(getX(d, i)) + margin.left) + ', ' + (y(getY(d, i)) + margin.top) + ')'; })
;
updateNode(nodeUpdate);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr('transform', function(d, i) { return 'translate(' + (x(getX(d, i)) + margin.left) + ', ' + (margin.top+h) + ')'; })
.remove()
;
exitNode(nodeExit);
if(showXAxis){
var xA = vis.select('g.xAxis');
if(!xA[0][0]){
xA = vis.append('g')
.attr('class', 'axis xAxis')
.attr('transform', 'translate(' + margin.left + ',' + (h+margin.top) + ')')
.call(xAxis)
;
}else{
xA.transition()
.duration(duration)
.call(xAxis)
;
}
xA.selectAll('line')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
xA.selectAll('path')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
}
if(showYAxis){
var yA = vis.select('g.yAxis');
if(!yA[0][0]){
yA = vis.append('g')
.attr('class', 'axis yAxis')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(yAxis)
;
}else{
yA.transition()
.duration(duration)
.call(yAxis)
;
}
yA.selectAll('line')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
yA.selectAll('path')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
}
if(style){
var key;
for(key in style){
vis.selectAll(key).attr('style', style[key]);
}
}
if(onUpdate){
onUpdate(vis);
}
});
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return getX;
getX = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return getY;
getY = _;
return chart;
};
chart.text = function(_) {
if (!arguments.length) return getText;
getText = _;
return chart;
};
chart.size = function(_) {
if (!arguments.length) return getR;
if(typeof(_)==='function'){
getR = _;
}else{
getR = function(){
return _;
}
}
return chart;
};
chart.duration = function(_) {
if (!arguments.length) return duration;
duration = _;
return chart;
};
chart.identity = function(_) {
if (!arguments.length) return identity;
identity = _;
return chart;
};
chart.style = function(_) {
if (!arguments.length) return style;
style = _;
return chart;
};
chart.xAxis = function(_){
if (!arguments.length) return showXAxis;
showXAxis = !!_;
return chart;
};
chart.yAxis = function(_){
if (!arguments.length) return showYAxis;
showYAxis = !!_;
return chart;
};
chart.scaleX = function(_) {
if (!arguments.length) return getScaleX;
getScaleX = _;
return chart;
};
chart.scaleY = function(_) {
if (!arguments.length) return getScaleY;
getScaleY = _;
return chart;
};
chart.nodeEnter = function(_){
if (!arguments.length) return enterNode;
enterNode = _;
return chart;
};
chart.nodeUpdate = function(_){
if (!arguments.length) return updateNode;
updateNode = _;
return chart;
};
chart.nodeExit = function(_){
if (!arguments.length) return exitNode;
exitNode = _;
return chart;
};
chart.colorize = function(_){
if (!arguments.length) return getColor;
getColor = _;
return chart;
};
chart.margin = function(_) {
if (!arguments.length) return margin;
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
return chart;
};
chart.updated = function(_){
if (!arguments.length) return onUpdate;
onUpdate = _;
return chart;
};
return chart;
};