Testing C3 Timeseries Chart
Last active
August 29, 2015 14:10
-
-
Save eesur/a9d87488a601bf6064e5 to your computer and use it in GitHub Desktop.
d3 | c3 Timeseries Chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*-- 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;*/ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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