Based on http://codepen.io/anon/pen/umArH, which is based on http://bost.ocks.org/mike/fisheye/
Inspired by http://www.nytimes.com/newsgraphics/2013/09/13/fashion-week-editors-picks/
Based on http://codepen.io/anon/pen/umArH, which is based on http://bost.ocks.org/mike/fisheye/
Inspired by http://www.nytimes.com/newsgraphics/2013/09/13/fashion-week-editors-picks/
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
text { | |
font: 10px sans-serif; | |
} | |
.background { | |
fill: none; | |
pointer-events: all; | |
} | |
#chart svg { | |
border: solid 1px #ccc; | |
} | |
.ytext{ | |
fill:white; | |
font-weight:bold; | |
pointer-events:none; | |
} | |
.ytext:hover { | |
cursor:default; | |
} | |
#chart line { | |
fill: none; | |
stroke: #ddd; | |
} | |
#chart line { | |
shape-rendering: crispEdges; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #fff; | |
shape-rendering: crispEdges; | |
} | |
.yrect{ | |
stroke:#fff; | |
stroke-opacity:0.3; | |
fill:#cac; | |
fill-opacity:0.5; | |
} | |
</style> | |
</head> | |
<body> | |
<p id="chart"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.8/d3.min.js"></script> | |
<script src="https://rawgithub.com/d3/d3-plugins/master/fisheye/fisheye.js"></script> | |
<script type="text/javascript"> | |
/* | |
Based on http://codepen.io/anon/pen/umArH, which is based on http://bost.ocks.org/mike/fisheye/ | |
*/ | |
var dataset = [], | |
rowLen = 1, | |
totalRows = 40; | |
var elGen = function(c) { | |
var e = {}; | |
e.val = c; | |
//cheap random but repeatable colors: | |
e.col = ('#'+ parseInt(c % 255, 16) + | |
parseInt(255 - (c % 255), 16) + | |
"000000").substr(0,7); | |
return e; | |
} | |
for(var c = 0,len = totalRows; c < len; c++) { | |
dataset.push(elGen(c)); | |
} | |
(function chart() { | |
var width = 600, | |
height = 600, | |
boxes = totalRows, | |
xSteps = d3.range(0, width, width/totalRows), | |
ySteps = d3.range(0, height, height/totalRows), | |
boxSteps = d3.range(boxes*boxes); | |
//set scale and origin focus | |
var xFisheye = d3.fisheye.scale(d3.scale.identity).domain([0, width]).focus(width/2), | |
yFisheye = d3.fisheye.scale(d3.scale.identity).domain([0, height]).focus(height/2); | |
fontSizeFisheye = d3.fisheye.scale(d3.scale.log).domain([3,150]).range([8,15]).focus(12), | |
fontOpacityFisheye = d3.fisheye.scale(d3.scale.log).domain([8,50]).range([0,1]).focus(1); | |
var svg = d3.select("#chart").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("transform", "translate(-.5,-.5)"); | |
svg.append("rect") | |
.attr("class", "background") | |
.attr("width", width) | |
.attr("height", height); | |
var boxTest = svg.selectAll(".yrect") | |
.data(dataset) | |
.enter().append("rect") | |
.attr("class", "yrect") | |
.style("fill",function(d,i) { | |
return d.col; | |
}) | |
.attr("id", function(d, i) { | |
return i; | |
}); | |
var yText = svg.selectAll("ytext") | |
.data(dataset) | |
.enter().append("text") | |
.text(function(d,i){return d.val}) | |
.attr("class", "ytext") | |
.attr("text-anchor", "middle"); | |
redraw(); | |
reset(); | |
svg.on("mousemove", function() { | |
var mouse = d3.mouse(this); | |
xFisheye.focus(mouse[0]); | |
yFisheye.focus(mouse[1]); | |
redraw(); | |
}); | |
svg.on("mouseout", function() { | |
reset(); | |
}); | |
function redraw() { | |
yText | |
.attr("x", function(d, i) { | |
return xFisheye(xSteps[i%rowLen]) + (xFisheye(xSteps[(i+1)%rowLen] || width) - xFisheye(xSteps[i%rowLen]))/2; | |
}) | |
.attr("y", function(d, i) { | |
var rowNum = Math.floor(i/rowLen); | |
return yFisheye(ySteps[rowNum]) + (yFisheye(ySteps[rowNum+1] || height) - yFisheye(ySteps[rowNum]))/2; | |
}) | |
.style("font-size",function(d,i){ | |
var rowNum = Math.floor(i/rowLen); | |
var xx = (xFisheye(xSteps[(i+1)%rowLen] || width) - xFisheye(xSteps[(i)%rowLen])); | |
var yy = (yFisheye(ySteps[rowNum+1]|| height) - yFisheye(ySteps[rowNum])); | |
var minDim = d3.min([xx,yy]); | |
return fontSizeFisheye(minDim); | |
}) | |
.style("fill-opacity",function(d,i){ | |
var rowNum = Math.floor(i/rowLen); | |
var xx = (xFisheye(xSteps[(i+1)%rowLen] || width) - xFisheye(xSteps[(i)%rowLen])); | |
var yy = (yFisheye(ySteps[rowNum+1] || height) - yFisheye(ySteps[rowNum])); | |
var minDim = d3.min([xx,yy]); | |
return fontOpacityFisheye(minDim); | |
}) | |
.attr("dy",function(d,i){ | |
var rowNum = ((i % totalRows) > 0) ? (i % totalRows) : 1 ; | |
var yy = (yFisheye(ySteps[rowNum]) - yFisheye(ySteps[rowNum-1])); | |
return (fontSizeFisheye(yy)/2); | |
}); | |
boxTest | |
.attr("x", function(d,i) { | |
return xFisheye(xSteps[i%rowLen]); | |
}) | |
.attr("y", function(d,i) { | |
var rowNum = Math.floor(i/rowLen); | |
return yFisheye(ySteps[rowNum-1] || 0) + (yFisheye(ySteps[rowNum]) - yFisheye(ySteps[rowNum-1] || 0)); | |
}) | |
.attr("width", function(d,i) { | |
var rowNum = Math.floor(i/rowLen); | |
return (xFisheye(xSteps[(i+1)%rowLen] || width) - xFisheye(xSteps[i%rowLen])); | |
}) | |
.attr("height", function(d,i) { | |
var rowNum = Math.floor(i/rowLen); | |
return (yFisheye(ySteps[rowNum+1]|| height) - yFisheye(ySteps[rowNum])); | |
}); | |
} | |
function reset() { | |
d3.selectAll(".yrect") | |
.attr("height", function(d, i) { | |
return height/totalRows; | |
}) | |
.attr("y", function(d, i) { | |
return i * (height/totalRows); | |
}); | |
svg.selectAll(".ytext") | |
.attr("x", function(d, i) { | |
return width/2; | |
}) | |
.attr("y", function(d, i) { | |
return (i * totalRows) + 10; | |
}) | |
.style("font-size",function(d,i){ | |
return totalRows * 0.7; | |
}) | |
.style("fill-opacity",function(d,i){ | |
return 0; | |
}); | |
} | |
})(); | |
</script> | |
</body> | |
</html> |