Skip to content

Instantly share code, notes, and snippets.

@eesur
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eesur/a9d87488a601bf6064e5 to your computer and use it in GitHub Desktop.
Save eesur/a9d87488a601bf6064e5 to your computer and use it in GitHub Desktop.
d3 | c3 Timeseries Chart

Testing C3 Timeseries Chart

/*-- Chart --*/
.c3 svg {
font: 11px monospace;;
}
.c3 path, .c3 line {
fill: none;
stroke: #000;
}
.c3 text {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.c3-legend-item-tile,
.c3-xgrid-focus,
.c3-ygrid,
.c3-event-rect,
.c3-bars path {
shape-rendering: crispEdges;
}
.c3-chart-arc path {
stroke: #fff;
}
.c3-chart-arc text {
fill: #fff;
font-size: 13px;
}
/*-- Axis --*/
.c3-axis-x .tick {
}
.c3-axis-x-label {
}
.c3-axis-y .tick {
}
.c3-axis-y-label {
}
.c3-axis-y2 .tick {
}
.c3-axis-y2-label {
}
/*-- Grid --*/
.c3-grid line {
stroke: #aaa;
}
.c3-grid text {
fill: #aaa;
}
.c3-xgrid, .c3-ygrid {
stroke-dasharray: 3 3;
}
.c3-xgrid-focus {
}
/*-- Text on Chart --*/
.c3-text {
}
.c3-text.c3-empty {
fill: #808080;
font-size: 2em;
}
/*-- Line --*/
.c3-line {
stroke-width: 1px;
}
/*-- Point --*/
.c3-circle._expanded_ {
stroke-width: 1px;
stroke: white;
}
.c3-selected-circle {
fill: white;
stroke-width: 2px;
}
/*-- Bar --*/
.c3-bar {
stroke-width: 0;
}
.c3-bar._expanded_ {
fill-opacity: 0.75;
}
/*-- Arc --*/
.c3-chart-arcs-title {
font-size: 1.3em;
}
/*-- Focus --*/
.c3-target.c3-focused {
opacity: 1;
}
.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
stroke-width: 2px;
}
.c3-target.c3-defocused {
opacity: 0.3 !important;
}
/*-- Region --*/
.c3-region {
fill: steelblue;
fill-opacity: .1;
}
/*-- Brush --*/
.c3-brush .extent {
fill-opacity: .1;
}
/*-- Select - Drag --*/
.c3-dragarea {
}
/*-- Legend --*/
.c3-legend-item {
font-size: 12px;
}
.c3-legend-background {
opacity: 0.75;
fill: white;
stroke: lightgray;
stroke-width: 1
}
/*-- Tooltip --*/
.c3-tooltip-container {
z-index: 10;
}
.c3-tooltip {
border-collapse:collapse;
border-spacing:0;
background-color:#fff;
empty-cells:show;
-webkit-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
-moz-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
box-shadow: 7px 7px 12px -9px rgb(119,119,119);
opacity: 0.9;
}
.c3-tooltip tr {
border:1px solid #CCC;
}
.c3-tooltip th {
background-color: #aaa;
font-size:14px;
padding:2px 5px;
text-align:left;
color:#FFF;
}
.c3-tooltip td {
font-size:13px;
padding: 3px 6px;
background-color:#fff;
border-left:1px dotted #999;
}
.c3-tooltip td > span {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 6px;
}
.c3-tooltip td.value{
text-align: right;
}
.c3-area {
stroke-width: 0;
opacity: 0.2;
}
.c3-chart-arcs .c3-chart-arcs-background {
fill: #e0e0e0;
stroke: none;
}
.c3-chart-arcs .c3-chart-arcs-gauge-unit {
fill: #000;
font-size: 16px;
}
.c3-chart-arcs .c3-chart-arcs-gauge-max {
fill: #777;
}
.c3-chart-arcs .c3-chart-arcs-gauge-min {
fill: #777;
}
.c3-chart-arc .c3-gauge-value {
fill: #000;
/* font-size: 28px !important;*/
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>d3 | c3 Timeseries Chart test</title>
<link href="c3.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.2/d3.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.4/c3.min.js"></script>
<style>
body {font-family: monospace; line-height: 140%; font-size: 18px; }
</style>
</head>
<body>
<div class='chart'>
<div id='chart'></div>
</div>
<script type="text/javascript">
var chart = c3.generate({
data: {
x: 'x',
// xFormat: '%Y%m%d', // 'xFormat' can be used as custom format of 'x'
columns: [
['x', '2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06'],
// ['x', '20130101', '20130102', '20130103', '20130104', '20130105', '20130106'],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 340, 200, 500, 250, 350],
['data3', 70, 220, 200, 100, 600, 512]
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d'
}
}
}
});
setTimeout(function () {
chart.load({
columns: [
['data4', 400, 500, 450, 700, 600, 100]
]
});
}, 1000);
</script>
</body>
</html>
</html>
// START FUNCTION: This function creates the canvas, the everything bundle within the canvas, the axes (given scale functions), and the axes labels
start = function(xLab,yLab,xMap,yMap,canvasWidth,canvasHeight,width,height,selector){
var canvas = d3.select(selector)
.append('svg')
.attr('height',canvasHeight)
.attr('width', canvasWidth);
var everything = canvas.append('g');
everything.attr('transform','translate('+(width * 0.2)+','+height*0.1+')');
var xAxis = d3.svg.axis()
.scale(xMap);
var yAxis = d3.svg.axis()
.scale(yMap)
.orient('left');
everything.append('g')
.attr('transform','translate(0,'+height+')')
.call(xAxis);
everything.append('g')
.call(yAxis);
var xLabel = everything.append('text')
.attr('x',canvasWidth*0.4)
.attr('y',height+45)
.text(xLab)
.attr('text-anchor','middle');
var yLabel = everything.append('text')
.attr('x', -canvasHeight*0.4)
.attr('y', -canvasWidth*0.1)
.attr('transform','rotate(-90)')
.text(yLab)
.attr('text-anchor','middle');
var objects = [canvas,everything];
return objects;
}
// END OF START FUNCTION
// HISTO FUNCTION: creats histogram plot
histo = function(data,config){
if (typeof config === 'undefined'){config = {}};
var xLab=config.xLab,selector=config.selector,canvasWidth=config.width,canvasHeight=config.height;
if(typeof canvasWidth === 'undefined'){
canvasWidth = 500;
}
if(typeof canvasHeight === 'undefined'){
canvasHeight = 500;
}
if(typeof selector === 'undefined'){
selector = 'body';
}
if(typeof xLab === 'undefined'){
xLab = '';
}
var hist = function(arr){
var newArr = arr.slice().sort(function(a,b){
return a-b;
});
var max = newArr[arr.length -1];
var min = newArr[0];
var bins = Math.round(Math.sqrt(arr.length));
var binSize = (max-min)/bins;
var obj= {};
var keys = [];
for (var i=0; i<bins; i++){
var key = min + (i*binSize);
keys.push(key);
obj[key] = 0;
}
for (var j=0; j<arr.length; j++){
var val = min;
var temp_key = 0;
while(true){
if (newArr[j] == newArr[newArr.length-1]){
obj[keys[keys.length-1]] += 1;
break;
}
else if (newArr[j]<val+binSize){
obj[keys[temp_key]]+= 1;
break;
}
else{
temp_key += 1;
val += binSize;
}
}
}
return [obj,min,max,binSize];
};
var height = canvasHeight/1.3;
var width = canvasWidth/1.3;
if (canvasHeight - height < 75){height -= 45};
var allData = hist(data);
var xMap = d3.scale.linear()
.domain([allData[1],allData[2]])
.range([0,width]);
var maxfreq = Math.max.apply( null,Object.keys(allData[0]).map(function ( key ) { return allData[0][key]; }) );
var yMap = d3.scale.linear()
.domain([maxfreq,0])
.range([0,height]);
var objects = start(xLab,'Frequency',xMap,yMap,canvasWidth,canvasHeight,width,height,selector);
var canvas = objects[0];
var everything = objects[1];
//MAKE AN ARRAY OF THE DATA TO BIND
var obj = allData[0];
var keys = Object.keys(obj);
var arr = [];
for (var i=0;i<keys.length;i++){
arr.push(obj[keys[i]]);
}
// obj,min,max,binSize
var binSize = xMap(allData[3] + allData[1]);
var padding = binSize * 0.075;
//padding used to create a buffer around each bin
everything.selectAll('rect')
.data(arr)
.enter()
.append('rect')
.attr('x', function(d,index){
return (index*binSize + padding/2);
})
.attr('y', function(d){
return yMap(d);
})
.attr('height', function(d){
return Math.max(yMap(maxfreq - d) - 0.5, 0);
})
.attr('width', binSize-padding)
.style('fill', 'steelBlue');
return canvas;
};
// END OF HIST FUNCTION
// BEGINNING OF XY PLOT FUNCTION
xyPlot = function(x,y,config){
if (typeof config === 'undefined'){config = {}};
var xLab=config.xLab,yLab=config.yLab,selector=config.selector,canvasWidth=config.width,canvasHeight=config.height;
if(typeof canvasWidth === 'undefined'){
canvasWidth = 500;
}
if(typeof canvasHeight === 'undefined'){
canvasHeight = 500;
}
if(typeof selector === 'undefined'){
selector = 'body';
}
var xSort = x.slice().sort(function(a,b){
return a-b;
});
var ySort = y.slice().sort(function(a,b){
return a-b;
});
var yMax = ySort[ySort.length-1];
var yMin = ySort[0];
var height = canvasHeight/1.3;
var width = canvasWidth/1.3;
if (canvasHeight - height < 75){height -= 45};
if (typeof x[0] !== 'number'){
if (typeof Date.parse(x[0]) === 'number'){
// if we're here, x[0] is a date
var xMap = d3.time.scale()
.domain([new Date(x[0]),new Date(x[x.length-1])])
.range([0,width]);
x.forEach(function(element,index){
x[index] = new Date(x[index]);
});
}
}
else{
// boundaries for numeric x
var xMax = xSort[xSort.length-1];
var xMin = xSort[0];
var xMap = d3.scale.linear()
.domain([xMin,xMax])
.range([0,width]);
}
var yMap = d3.scale.linear()
.domain([yMax,yMin])
.range([0,height]);
var objects = start(xLab,yLab,xMap,yMap,canvasWidth,canvasHeight,width,height,selector);
var canvas = objects[0];
var everything = objects[1];
for (var i=1;i<x.length;i++){
everything.append('line')
.attr('stroke-width',1)
.attr('stroke','black')
.attr('x1',xMap(x[i-1]))
.attr('x2',xMap(x[i]))
.attr('y1',yMap(y[i-1]))
.attr('y2',yMap(y[i]));
}
return canvas;
};
// START OF SCATTER FUNCTION
scatter = function(x,y,config){
if (typeof config === 'undefined'){config = {}};
var xLab=config.xLab,yLab=config.yLab,selector=config.selector,canvasWidth=config.width,canvasHeight=config.height,z=config.size,zLab=config.sizeLab;
if(typeof canvasWidth === 'undefined'){
canvasWidth = 500;
}
if(typeof canvasHeight === 'undefined'){
canvasHeight = 500;
}
if(typeof selector === 'undefined'){
selector = 'body';
}
var xSort = x.slice().sort(function(a,b){
return a-b;
});
var ySort = y.slice().sort(function(a,b){
return a-b;
});
if (typeof z !== 'undefined'){
var zSort = z.slice().sort(function(a,b){
return a-b;
});
}
var yMax = ySort[ySort.length-1];
var yMin = ySort[0];
var height = canvasHeight/1.3;
var width = canvasWidth/1.3;
if (canvasHeight - height < 75){height -= 45};
if (typeof x[0] !== 'number'){
if (typeof Date.parse(x[0]) === 'number'){
// if we're here, x[0] is a date
var xMap = d3.time.scale()
.domain([new Date(x[0]),new Date(x[x.length-1])])
.range([0,width]);
x.forEach(function(element,index){
x[index] = new Date(x[index]);
});
}
}
else{
// boundaries for numeric x
var xMax = xSort[xSort.length-1];
var xMin = xSort[0];
var xMap = d3.scale.linear()
.domain([xMin,xMax])
.range([0,width]);
}
var yMap = d3.scale.linear()
.domain([yMax,yMin])
.range([0,height]);
if (typeof zLab !== 'undefined'){yLab = yLab+' ('+zLab+')'};
var objects = start(xLab,yLab,xMap,yMap,canvasWidth,canvasHeight,width,height,selector);
var canvas = objects[0];
var everything = objects[1];
x.forEach(function(elem,index){
everything.append('circle')
.attr('r',function(){
if (typeof z === 'undefined'){
return height*width*(0.00002);
}
else{
return (height*width*0.000025 + (z[index]-zSort[0])*(height*width*(0.0001))/(zSort[zSort.length-1] - zSort[0]));
}
})
.attr('cx',xMap(x[index]))
.attr('cy',yMap(y[index]))
.attr('opacity',function(){
if (typeof z === 'undefined'){
return 1;
}
else{
return 0.3;
}
})
.attr('fill',function(){
if (typeof z === 'undefined'){
return 'none';
}
else{
return 'steelBlue';
}
})
.attr('stroke', function(){
if (typeof z === 'undefined'){return'black'};
return 'none'
});
});
return canvas;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment