|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script src="https://d3js.org/d3-random.v1.min.js"></script> |
|
<script src="https://d3js.org/d3-axis.v1.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
circle { fill: #777; } |
|
.axis line{stroke: #ccc; stroke-width: 2px } |
|
.axis path{ stroke: #ccc; stroke-width: 2px } |
|
.axis text{ fill: #ccc; } |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<script> |
|
// Feel free to change or delete any of the code you see in this editor! |
|
const svg = d3.select("body").append("svg") |
|
.attr("width", 960) |
|
.attr("height", 500) |
|
|
|
const overlay = svg.append("text") |
|
.attr("fill", "red") |
|
.attr("font-size", "48px") |
|
.attr("font-family", "avenir, sans-serif") |
|
.attr("transform", "translate(30, 70)") |
|
|
|
const horizontalBaseline = 450 |
|
const r = 3.76 |
|
|
|
const generator = d3.randomBates(20) |
|
const data = d3.range(200).map(() => generator()*280).sort() |
|
const x = d3.scaleLinear() |
|
.domain([90, 190]) |
|
.range([50, 910]) |
|
|
|
const axis = svg.append("g") |
|
.attr("class", "axis") |
|
.attr("transform", `translate(0,${horizontalBaseline + r})`) |
|
.call(d3.axisBottom(x)); |
|
|
|
const transitionDelay = 2000 |
|
const transitionDuration = 3000 |
|
|
|
const precision = d3.precisionRound(0.01, 200) |
|
const numFormat = d3.format("." + precision + "r"); |
|
|
|
var lastBand = 0 |
|
var indexInBand = 0 |
|
const wheatVerticalOffset = r*2.3 |
|
const bandWidth = 10 |
|
|
|
svg.append("g") |
|
.attr("class", "data") |
|
.selectAll("circle") |
|
.data(data) |
|
.enter() |
|
.append("circle") |
|
.attr("r", r) |
|
.attr("cx", d => x(d)) |
|
.attr("cy", horizontalBaseline) |
|
.on("mouseenter", function(d){ |
|
overlay.text(numFormat(d)) |
|
d3.select(this).style('fill', 'red') |
|
}) |
|
.on("mouseleave", function(d){ |
|
overlay.text(undefined) |
|
d3.select(this).style('fill', undefined) |
|
}) |
|
.transition() |
|
.delay(transitionDelay) |
|
.duration(transitionDuration) |
|
.attr("cy", function(d){ |
|
const band = Math.floor(d/bandWidth)*bandWidth |
|
if (band !== lastBand){ |
|
lastBand = band |
|
indexInBand = 0 |
|
}else{ |
|
indexInBand++ |
|
} |
|
return horizontalBaseline - indexInBand * wheatVerticalOffset |
|
}) |
|
|
|
axis.selectAll(".tick") |
|
.select("line") |
|
.attr("y1", "0") |
|
.transition() |
|
.delay(transitionDelay) |
|
.duration(transitionDuration) |
|
.attr("y1", -1*horizontalBaseline+40) |
|
|
|
|
|
|
|
|
|
</script> |
|
</body> |