我正在使用d3.js仪表板(因此只有一个仪表板和许多布局)。我想显示一个动画的散点图,其中的点移动了我正在申请的一些过滤器。
但是为了顺序,我必须首先展示一些没有发生的事情。
这是我的程序,它是MVC格式的scatterplot.js
文件。
function scatterplot(DOMElement){
var scatObj = {}; // main object
scatObj.setTooltipText = function(f){
tooltipText = f;
//updateInteractions();
return scatObj;
}
scatObj.setMouseclickCallback = function(f){
mouseclickCallback = f;
//updateInteractions();
return scatObj;
}
// function loading data and rendering it in scatter chart
// parameters:
// - dataset in following format:
// [{"key": year, "value": money}, {...}, ...]
// returns:
// - scatObj for chaining
scatObj.loadAndRender = function(data){
dataset = data;
render();
return scatObj;
}
// ---- PRIVATE VARIABLES
// sizing vars
var dataset = []; // Initialize empty array
var numDataPoints = dataset.length;
for(var i=0; i<numDataPoints; i++) {
var newNumber1 = d.value.x; // New random integer
var newNumber2 = d.value.y; // New random integer
dataset.push([newNumber1, newNumber2]); // Add new number to array
}
// Setup settings for graphic
var canvas_width = 500;
var canvas_height = 300;
var padding = 30; // for chart edges
// Create scale functions
var xScale = d3.scaleLinear() // xScale is width of graphic
.domain([0, d3.max(dataset, function(d) {
return d[0]; // input domain
})])
.range([padding, canvas_width - padding * 2]); // output range
var yScale = d3.scaleLinear() // yScale is height of graphic
.domain([0, d3.max(dataset, function(d) {
return d[1]; // input domain
})])
.range([canvas_height - padding, padding]); // remember y starts on top going down so we flip
// scales
// Define X axis
var xAxis = d3.axisBottom()
.scale(xScale)
// Define Y axis
var yAxis = d3.axisLeft()
.scale(yScale)
var svg = d3.select("DOMElement") // This is where we put our vis
.append("svg")
.attr("width", canvas_width)
.attr("height", canvas_height);
var tooltip = d3.select(DOMElement).append("div")
.classed("tooltip", true);
// interaction settings
var tooltipText = function(d, i){return "tooltip over element "+i;}
var mouseoverCallback = function(d, i){ };
var mouseoutCallback = function(d, i){ };
var mouseclickCallback = function(d, i){ console.log(d,i)};
var keySelected = null;
// ---- PRIVATE FUNCTIONS
function render(){
GUP_scat();
}
function GUP_scat(){
// GUP
// Create Circles
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle") // Add circle svg
.attr("cx", function(d) {
return xScale(d[0]); // Circle's X
})
.attr("cy", function(d) { // Circle's Y
return yScale(d[1]);
})
.attr("r", 2); // radius
// Add to X axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (canvas_height - padding) +")")
.call(xAxis);
// Add to Y axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + padding +",0)")
.call(yAxis);
// On click, update with new data
d3.select(DOMElement)
.on("click", function() {
keySelected = (keySelected == d.key) ? null : d.key;
var numValues = dataset.length; // Get original dataset's length
dataset = []; // Initialize empty array
for(var i=0; i<numValues; i++) {
var newNumber1 = d.value.x; // Random int for x
var newNumber2 = d.value.y; // Random int for y
dataset.push([newNumber1, newNumber2]); // Add new numbers to array
}
// Update scale domains
xScale.domain([0, d3.max(dataset, function(d) {
return d[0]; })]);
yScale.domain([0, d3.max(dataset, function(d) {
return d[1]; })]);
// Update circles
svg.selectAll("circle")
.data(dataset) // Update with new data
.transition() // Transition from old to new
.duration(1000) // Length of animation
.each("start", function() { // Start animation
d3.select(this) // 'this' means the current element
.attr("fill", "red") // Change color
.attr("r", 5); // Change size
})
.delay(function(d, i) {
return i / dataset.length * 500; // Dynamic delay (i.e. each item delays a little longer)
})
//.ease("linear") // Transition easing - default 'variable' (i.e. has acceleration), also: 'circle', 'elastic', 'bounce', 'linear'
.attr("cx", function(d) {
return xScale(d[0]); // Circle's X
})
.attr("cy", function(d) {
return yScale(d[1]); // Circle's Y
})
.each("end", function() { // End animation
d3.select(this) // 'this' means the current element
.transition()
.duration(500)
.attr("fill", "black") // Change color
.attr("r", 2); // Change radius
});
// Update X Axis
svg.select(".x.axis")
.transition()
.duration(1000)
.call(xAxis);
// Update Y Axis
svg.select(".y.axis")
.transition()
.duration(100)
.call(yAxis);
mouseclickCallback(d, i);
});}
return scatObj; // returning the main object
}
我在main.js文件中这样称呼它:
dash.append('div').attr('id', 'scat1').classed("scatterplot", true)
.append("h3").text("Per Scateub");
var scat1 = scatterplot("div#scat1")
.setTooltipText(function(d, i){
return "<b>"+d.data.key +" : "+d3.format(",.2f")(d.value)+"</b> /10 ";
})
.loadAndRender(dataManager.getFteOverall());
scat1.setMouseclickCallback(function(d, i){
dataManager.setNameFilter(d.key);
redraw();
})
这是我的巢穴:
dmObj.getFteOverall= function(){
var nestedData = d3.nest()
.key(function(d){ return d.naAsses;})
.rollup(function (v) { return {
x: d3.sum(v,function(d){
return (d.four*4,d.three*3,d.two*2,d.one)/100 }),
y: d3.sum(v, function(d){
return (d.fte)
}
)
};
})
.sortKeys(d3.ascending)
.entries(filteredData());
return nestedData;
}
我知道这似乎有点愚蠢的问题,但我一直在努力,而且我已经被困了一段时间。 我希望我很清楚,你将能够帮助我(以防万一我正在使用d3 V4)。 感谢先进的人。