Skip to content

Instantly share code, notes, and snippets.

@mgold
Last active June 14, 2017 06:37
Show Gist options
  • Save mgold/726a7dff35fa117b78a03f99edabe309 to your computer and use it in GitHub Desktop.
Save mgold/726a7dff35fa117b78a03f99edabe309 to your computer and use it in GitHub Desktop.
Wheat Plot
license: mit

This is a simple wheat plot implementation, taken from a recent document from Stephen Few. It is designed so that one can see a histogram-like distribution of values, but also each value individually.

The data are randomly generated. Mouse over any one of them to see its value, an advantage of wheat plots on computer screens.

Built with blockbuilder.org

<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment