See it running at http://bl.ocks.org/3867599
Modified from here: http://jsfiddle.net/cuHrV/
See it running at http://bl.ocks.org/3867599
Modified from here: http://jsfiddle.net/cuHrV/
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"> | |
<title>Scatter to Heatmap</title> | |
<script src="http://d3js.org/d3.v2.js"></script> | |
<script src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> | |
<link href='http://fonts.googleapis.com/css?family=Numans' rel='stylesheet' type='text/css'> | |
<style> | |
body { | |
font-family: 'Numans', sans-serif; | |
} | |
div#plots { | |
margin-bottom: 15px; | |
} | |
div#scatterplot, div#heatchart { | |
border: 1px solid #ccc; | |
margin-bottom: 10px; | |
} | |
div#scatterContainer, div#heatchartContainer { | |
float: left; | |
margin-left: 15px; | |
margin-bottom: 20px; | |
} | |
circle { | |
fill: #063; | |
} | |
</style> | |
<h1>Scatter to Heatmap</h1> | |
<div id="plots"> | |
<div id="scatterContainer"> | |
<div id="scatterplot"></div> | |
</div> | |
<div id="heatchartContainer"> | |
<div id="heatchart"></div> | |
</div> | |
</div> | |
<script type="text/javascript"> | |
var numPoints = 1500, | |
size = 300, | |
numRows = 16, | |
numCols = 16, | |
showingScatter = true, | |
scatterDirty = false, | |
data = null, | |
cells = null, | |
color = d3.interpolateRgb("#fff", "#063"); | |
var getEmptyCells = function() { | |
var emptyCells = []; | |
for (var rowNum = 0; rowNum < numRows; rowNum++) { | |
emptyCells.push([]); | |
var row = emptyCells[emptyCells.length - 1]; | |
for (var colNum = 0; colNum < numCols; colNum++) { | |
row.push({ | |
row: rowNum, | |
col: colNum, | |
density: 0, | |
points: [] | |
}); | |
} | |
} | |
return emptyCells; | |
}; | |
var clearCells = function() { | |
for (var rowNum = 0; rowNum < numRows; rowNum++) { | |
for (var colNum = 0; colNum < numCols; colNum++) { | |
cells[rowNum][colNum].density = 0; | |
cells[rowNum][colNum].points = []; | |
} | |
} | |
}; | |
var randomizeData = function() { | |
data = []; | |
if (cells === null) { | |
cells = getEmptyCells(); | |
} | |
else { | |
clearCells(); | |
} | |
var x, y, col, row; | |
for (var i = 0; i < numPoints; i++) { | |
x = Math.random() * size; | |
y = Math.random() * size; | |
col = Math.min(Math.floor(x / size * numCols), numCols - 1); | |
row = Math.min(Math.floor(y / size * numRows), numRows - 1); | |
data.push({ | |
x: x, | |
y: y, | |
col: col, | |
row: row, | |
cell: cells[row][col], | |
ind: i | |
}); | |
cells[row][col].points.push(data[data.length - 1]); | |
} | |
}; | |
var selectPoints = function(points) { | |
d3.selectAll(points).attr("r", 4).attr("stroke", "#f00").attr("stroke-width", 3); | |
for (var i = 0; i < points.length; i++) { | |
points[i].parentNode.appendChild(points[i]); | |
} | |
}; | |
var deselectPoints = function(points) { | |
d3.selectAll(points).attr("r", 2).attr("stroke", "none"); | |
}; | |
var selectCell = function(cell) { | |
d3.select(cell).attr("stroke", "#f00").attr("stroke-width", 3); | |
cell.parentNode.parentNode.appendChild(cell.parentNode); | |
cell.parentNode.appendChild(cell); | |
}; | |
var deselectCell = function(cell) { | |
d3.select(cell).attr("stroke", "#fff").attr("stroke-width", 1); | |
}; | |
var onPointOver = function(point, data) { | |
selectPoints([point]); | |
var cell = d3.select("div#heatchart").select('[cell="r' + data.row + 'c' + data.col + '"]'); | |
selectCell(cell.node()); | |
}; | |
var onPointOut = function(point, data) { | |
deselectPoints([point]); | |
var cell = d3.select("div#heatchart").select('[cell="r' + data.row + 'c' + data.col + '"]'); | |
deselectCell(cell.node()); | |
}; | |
var createScatterplot = function() { | |
var scatterplot = d3.select("div#scatterplot").append("svg:svg").attr("width", size).attr("height", size); | |
scatterplot.selectAll("circle").data(data).enter().append("svg:circle").attr("cx", function(d, i) { | |
return d.x; | |
}).attr("cy", function(d, i) { | |
return d.y; | |
}).attr("r", 2).attr("ind", function(d) { | |
return d.ind; | |
}).on("mouseover", function(d) { | |
onPointOver(this, d); | |
}).on("mouseout", function(d) { | |
onPointOut(this, d); | |
}); | |
}; | |
var onCellOver = function(cell, data) { | |
selectCell(cell); | |
if (showingScatter) { | |
var pointEls = []; | |
for (var i = 0; i < data.points.length; i++) { | |
pointEls.push(d3.select("div#scatterplot").select('[ind="' + data.points[i].ind + '"]').node()); | |
} | |
selectPoints(pointEls); | |
} | |
}; | |
var onCellOut = function(cell, data) { | |
deselectCell(cell); | |
if (showingScatter) { | |
var pointEls = []; | |
for (var i = 0; i < data.points.length; i++) { | |
pointEls.push(d3.select("div#scatterplot").select('[ind="' + data.points[i].ind + '"]').node()); | |
} | |
deselectPoints(pointEls); | |
} | |
}; | |
var updateScatterplot = function() { | |
// select | |
var dots = d3.select("div#scatterplot").select("svg").selectAll("circle").data(data); | |
// enter | |
dots.enter().append("svg:circle").attr("cx", function(d, i) { | |
return d.x; | |
}).attr("cy", function(d, i) { | |
return d.y; | |
}).attr("r", 2).attr("ind", function(d) { | |
return d.ind; | |
}).on("mouseover", function(d) { | |
onPointOver(this, d); | |
}).on("mouseout", function(d) { | |
onPointOut(this, d); | |
}); | |
// update | |
dots.attr("cx", function(d, i) { | |
return d.x; | |
}).attr("cy", function(d, i) { | |
return d.y; | |
}).attr("ind", function(d) { | |
return d.ind; | |
}).on("mouseover", function(d) { | |
onPointOver(this, d); | |
}).on("mouseout", function(d) { | |
onPointOut(this, d); | |
}); | |
// exit | |
dots.exit().remove(); | |
}; | |
var createHeatchart = function() { | |
var min = 999; | |
var max = -999; | |
var l; | |
for (var rowNum = 0; rowNum < cells.length; rowNum++) { | |
for (var colNum = 0; colNum < numCols; colNum++) { | |
l = cells[rowNum][colNum].points.length; | |
if (l > max) { | |
max = l; | |
} | |
if (l < min) { | |
min = l; | |
} | |
} | |
} | |
var heatchart = d3.select("div#heatchart").append("svg:svg").attr("width", size).attr("height", size); | |
heatchart.selectAll("g").data(cells).enter().append("svg:g").selectAll("rect").data(function(d) { | |
return d; | |
}).enter().append("svg:rect").attr("x", function(d, i) { | |
return d.col * (size / numCols); | |
}).attr("y", function(d, i) { | |
return d.row * (size / numRows); | |
}).attr("width", size / numCols).attr("height", size / numRows).attr("fill", function(d, i) { | |
return color((d.points.length - min) / (max - min)); | |
}).attr("stroke", "#fff").attr("cell", function(d) { | |
return "r" + d.row + "c" + d.col; | |
}).on("mouseover", function(d) { | |
onCellOver(this, d); | |
}).on("mouseout", function(d) { | |
onCellOut(this, d); | |
}); | |
}; | |
var updateHeatchart = function() { | |
var min = 999; | |
var max = -999; | |
var l; | |
for (var rowNum = 0; rowNum < cells.length; rowNum++) { | |
for (var colNum = 0; colNum < numCols; colNum++) { | |
l = cells[rowNum][colNum].points.length; | |
if (l > max) { | |
max = l; | |
} | |
if (l < min) { | |
min = l; | |
} | |
} | |
} | |
d3.select("div#heatchart").select("svg").selectAll("g").data(cells).selectAll("rect").data(function(d) { | |
return d; | |
}).attr("x", function(d, i) { | |
return d.col * (size / numCols); | |
}).attr("y", function(d, i) { | |
return d.row * (size / numRows); | |
}).attr("fill", function(d, i) { | |
return color((d.points.length - min) / (max - min)); | |
}).attr("cell", function(d) { | |
return "r" + d.row + "c" + d.col; | |
}).on("mouseover", function(d) { | |
onCellOver(this, d); | |
}).on("mouseout", function(d) { | |
onCellOut(this, d); | |
}); | |
}; | |
var onRandomizeClick = function() { | |
randomizeData(); | |
if (showingScatter) { | |
updateScatterplot(); | |
} | |
else { | |
scatterDirty = true; | |
} | |
updateHeatchart(); | |
}; | |
var onNumPointsChange = function(event) { | |
numPoints = event.target.options[event.target.selectedIndex].value; | |
randomizeData(); | |
if (showingScatter) { | |
updateScatterplot(); | |
} | |
else { | |
scatterDirty = true; | |
} | |
updateHeatchart(); | |
}; | |
var onShowScatterplotChange = function(event) { | |
showingScatter = event.target.checked; | |
if (showingScatter) { | |
if (scatterDirty) { | |
updateScatterplot(); | |
scatterDirty = false; | |
} | |
d3.select("div#scatterplot").select("svg").attr("visibility", "visible"); | |
} | |
else { | |
d3.select("div#scatterplot").select("svg").attr("visibility", "hidden"); | |
} | |
}; | |
var init = function() { | |
randomizeData(); | |
createScatterplot(); | |
createHeatchart(); | |
}; | |
init(); | |
</script> | |
</body> | |
</html> |