jam/js/d3/plot.js

246 lines
7.8 KiB
JavaScript

var fs = require('fs');
var d3 = require('./d3');
var D3Node = require('./d3-node');
function log(msg) {
console.log('[PLOT] '+msg);
}
/**
* generic options = {margin, padding}
*/
var Plot = function(options) {
var self=this;
// auto-new instance, so we always have 'this'
if (!(this instanceof Plot)) {
return new Plot(options)
}
this.options=options;
if (this.options.margin==undefined) this,options.margin=0;
if (this.options.padding==undefined) this,options.padding=0;
switch (options.type) {
case 'matrix':
if (!this.options.fontsize) this.options.fontsize=12;
case 'circle':
/* Circle 2D Scatter Plot
** Text 2D Matrix Plot
**
** type options = {
** x:number of circles/entries,y:number of circles/entries,
** size:number of circle/element size,
** color:string of circle fill color/text color,
** min:number of smallest data value, max: number of biggest data value
** grid:boolean for grid drawing,
** map: function (d,i,j) is a data set mapping functions
**
**/
if (!this.options.color) this.options.color='green';
this.d3n = new D3Node({d3Module:d3});
this.width = 2*this.options.margin+
2*this.options.padding+
this.options.size*(this.options.x+2);
this.height = 2*this.options.margin+
2*this.options.padding+
this.options.size*(this.options.y+2);
log('Size of diagram: width='+this.width+', height='+this.height+' px');
this.svg = this.d3n.createSVG()
.attr("width", this.width)
.attr("height", this.height);
break;
default:
throw Error ('[PLOT] Unknown plot diagram tyoe '+options.type);
}
}
Plot.prototype.plot = function (dataset) {
var self=this,
i,j,g,d;
if (!this.options.min) this.options.min=0;
if (!this.options.max) {
this.options.max=0;
for (j=0; j < dataset.length; j++)
for(i=0; i < dataset[j].length; i++) {
d=dataset[j][i];
if (this.options.map) d=this.options.map(d,i,j);
if (d> this.options.max) this.options.max= d;
}
}
log('Data set has min='+this.options.min+', max='+this.options.max);
switch (this.options.type) {
case 'circle':
d3.select(this.d3n.document.body)
if (this.options.grid) {
g=this.svg.append("g")
.selectAll("g")
.data(dataset)
.enter()
.append("g") //removing
.selectAll("text") // these
.data( function(d,i,j) { return d; } ) //lines
.enter()
g.append('rect')
.attr("x", function(d,i,j) {
return self.options.padding+
self.options.margin+
(i * self.options.size) + self.options.size/2;
})
.attr("y", function(d,i,j) {
return self.options.padding+
self.options.margin+
(j * self.options.size) + self.options.size/2;
})
.attr("width", function(d,i,j) {
return self.options.size
})
.attr("height", function(d,i,j) {
return self.options.size
})
.attr("stroke", function(d,i,j) {
return '#AAAAAA'
})
.attr("fill", function(d,i,j) {
return 'white'
});
}
g=this.svg.append("g")
.selectAll("g")
.data(dataset)
.enter()
.append("g") //removing
.selectAll("text") // these
.data( function(d,i,j) { return d; } ) //lines
.enter() // circle displays normally
g=g.append("circle")
.attr("cx", function(d,i,j) {
return self.options.padding+
self.options.margin+
(i * self.options.size) + self.options.size;
})
.attr("cy", function(d,i,j) {
return self.options.padding+
self.options.margin+(j * self.options.size) + self.options.size;
})
.attr("r", function(d,i,j) {
if (self.options.map) d=self.options.map(d,i,j);
return (
self.options.size/2*(
(d-self.options.min)/
(self.options.max-self.options.min))
);
})
.attr("fill", function(d,i,j) {
return self.options.color
});
break;
case 'matrix':
d3.select(this.d3n.document.body)
if (this.options.grid) {
g=this.svg.append("g")
.selectAll("g")
.data(dataset)
.enter()
.append("g") //removing
.selectAll("text") // these
.data( function(d,i,j) { return d; } ) //lines
.enter();
g.append('rect')
.attr("x", function(d,i,j) {
return self.options.padding+
self.options.margin+
(i * self.options.size) + self.options.size/2;
})
.attr("y", function(d,i,j) {
return self.options.padding+
self.options.margin+
(j * self.options.size) + self.options.size/2;
})
.attr("width", function(d,i,j) {
return self.options.size
})
.attr("height", function(d,i,j) {
return self.options.size
})
.attr("stroke", function(d,i,j) {
return '#AAAAAA'
})
.attr("fill", function(d,i,j) {
return 'white'
});
}
for(var index=0;index<(self.options.cell?self.options.cell.rows:1);index++) {
g=this.svg.append("g")
.selectAll("g")
.data(dataset)
.enter()
.append("g") //removing
.selectAll("text") // these
.data( function(d,i,j) { return d; } ) //lines
.enter(); // circle displays normal
g=g.append("text")
.attr("x", function(d,i,j) {
if (self.options.map) d=self.options.map(d,i,j);
if (self.options.cell && self.options.cell.rows) d=d[index];
return (self.options.padding+
self.options.margin-
(d.length*self.options.fontsize/3)+
(i * self.options.size) + self.options.size);
})
.attr("y", function(d,i,j) {
var off;
if (self.options.cell && self.options.cell.rows) {
switch (index) {
case 0: off=-self.options.fontsize; break;
case 1: off=self.options.fontsize; break;
default: off=0;
}
} else
off=self.options.fontsize/3;
return (self.options.padding+
off+
self.options.margin+(j * self.options.size) + self.options.size);
})
.attr("font-size", self.options.fontsize+'px')
.attr("color", function(d,i,j) {
return self.options.color
})
.attr("fill", function(d,i,j) {
return self.options.color
})
.text(function (d,i,j) {
var lines='';
if (self.options.map) d=self.options.map(d,i,j);
if (self.options.cell && self.options.cell.rows) d=d[index];
return d
});
}
break;
}
}
Plot.prototype.output = function (outputName) {
fs.writeFile(outputName+'.html', this.d3n.html(), function () {
log(outputName+'.html created.');
});
var svgBuffer = new Buffer(this.d3n.svgString(), 'utf-8');
fs.writeFile(outputName+'.svg', svgBuffer, function () {
log(outputName+'.svg created');
})
};
module.exports = {
Plot:Plot
}