In this block, I will demonstrate a way to draw a colour range legend using D3FC components. You can also read my blog post where I describe how I went about developing the legend https://blog.scottlogic.com/2019/03/13/how-to-create-a-continuous-colour-range-legend-using-d3-and-d3fc.
Last active
May 28, 2019 14:10
-
-
Save Ro4052/caaf60c1e9afcd8ece95034ea91e1eaa to your computer and use it in GitHub Desktop.
Continuous Colour Range Legend
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
license: mit |
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> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script> | |
<script src="https://unpkg.com/d3fc@14.0.27/build/d3fc.js"></script> | |
<style> | |
body { | |
margin: 0; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<script> | |
const container = d3.select("#chart"); | |
const colourScale = d3 | |
.scaleSequential(d3.interpolateViridis) | |
.domain([0, 22]); | |
const domain = colourScale.domain(); | |
const width = 100; | |
const height = 150; | |
const paddedDomain = fc.extentLinear() | |
.pad([0.1, 0.1]) | |
.padUnit("percent")(domain); | |
const [min, max] = paddedDomain; | |
const expandedDomain = d3.range(min, max, (max - min) / height); | |
const xScale = d3 | |
.scaleBand() | |
.domain([0, 1]) | |
.range([0, width]); | |
const yScale = d3 | |
.scaleLinear() | |
.domain(paddedDomain) | |
.range([height, 0]); | |
const svgBar = fc | |
.autoBandwidth(fc.seriesSvgBar()) | |
.xScale(xScale) | |
.yScale(yScale) | |
.crossValue(0) | |
.baseValue((_, i) => (i > 0 ? expandedDomain[i - 1] : 0)) | |
.mainValue(d => d) | |
.decorate(selection => { | |
selection.selectAll("path").style("fill", d => colourScale(d)); | |
}); | |
const axisLabel = fc | |
.axisRight(yScale) | |
.tickValues([...domain, (domain[1] + domain[0]) / 2]) | |
.tickSizeOuter(0); | |
const legendSvg = container.append("svg") | |
.attr("height", height) | |
.attr("width", width); | |
const legendBar = legendSvg | |
.append("g") | |
.datum(expandedDomain) | |
.call(svgBar); | |
const barWidth = Math.abs(legendBar.node().getBoundingClientRect().x); | |
legendSvg.append("g") | |
.attr("transform", `translate(${barWidth})`) | |
.datum(expandedDomain) | |
.call(axisLabel) | |
.select(".domain") | |
.attr("visibility", "hidden"); | |
container.style("margin", "1em"); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment