Testing D3xter straight forward plotting built on D3
Last active
August 29, 2015 14:10
d3 | d3xter
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>D3xter test</title> | |
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.2/d3.js"></script> | |
<script src="lib.js" charset="utf-8"></script> | |
<style> | |
body {font-family: monospace; line-height: 160%; font-size: 18px; } | |
svg path, svg line { | |
fill: none; | |
stroke: black; | |
} | |
svg text { | |
font-size: 11px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='elementID'></div> | |
<script type="text/javascript"> | |
var x = [-0.8234, 0.0952, 1.9594, -0.2831, -0.4147, 1.5859, 0.5326, 0.0925, 0.3293, 1.3635, 0.3396, 0.0677, -0.6739, 0.4084, -1.4487, -0.1101, -0.7521, -1.2118, 1.7191, 0.2020, -0.1573, -0.2298, -0.8230, 1.7924, 0.4511]; | |
var y = [-1.4166, 1.353, -0.6294, 0.0567, 1.4157, 0.32806, 0.2377, -0.2262, -1.0602, -1.8150, 0.1075, -1.3516, 1.0137, 0.0183, -0.5466, 0.6416, -0.6655, 0.6874, -0.4616, -0.2808, 1.3443, -1.0518, -0.1332, -1.0097, 0.3643]; | |
var z = [1.1011, 0.8724, -1.5972, -0.2027, -1.2296, -0.0543, 0.2415, 0.3584, 1.0202, -1.7524, -0.6787, 0.8113, 0.0206, -1.9769, 1.2008, 1.0440, 1.0141, -0.6452, -0.6115, 0.6687, 2.9415, -1.1146, -1.2889, -0.2562, -1.1781]; | |
var config = { | |
xLab: 'random x-values', //x-axis label (defaults to '') | |
yLab: 'random y-values', //y-axis label (defaults to '') | |
selector: '#elementID', //Selector for DOM element to append the plot to (defaults to < body >) | |
width: 900, //pixel width (defaults to 500) | |
height: 500, //pixel height (defaults to 500) | |
//size and sizeLab are used in bubble charts like the top-right example. | |
size: z, //array of numeric values which map to sizes of the circles plotted at the corresponding x-y point (defaults to undefined for a standard scatter) | |
sizeLab: 'random size values' //label for size values (defaults to '') | |
} | |
var scatter = scatter(x,y,config); | |
//modify the color of the circles with D3 syntax | |
scatter.selectAll('circle').style('fill','#EE3124'); | |
</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