Skip to content

Instantly share code, notes, and snippets.

@statsracecarstats
Last active September 1, 2018 02:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save statsracecarstats/731c7e1ca9ef4f1ed51f2b420a79ca92 to your computer and use it in GitHub Desktop.
Save statsracecarstats/731c7e1ca9ef4f1ed51f2b420a79ca92 to your computer and use it in GitHub Desktop.
Bar graph with constant gradient using D3

This script is an example of how to create a constant gradient across multiple svg objects, such as bars in a bar graph. Based off an example by Mike Bobstock, modified to extend across multiple bars.

Data presented in example are various meltal's melting points. Data collected from: The Engineering ToolBox, 'Metals - Melting Temperatures', https://www.engineeringtoolbox.com/melting-temperature-metals-d_860.html. Collected August 25th, 2018.

<!DOCTYPE html>
<html>
<body>
</body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var width = 1000;
var height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
//simple data set to make bar graph from
//data gathered from the engineering toolbox (www.EngineeringToolBox.com)
var MeltingPoints = [
{"Metal": "Tungsten", "MeltingPoint": 3400},
{"Metal": "Molybdenum", "MeltingPoint": 2620},
{"Metal": "Titanium", "MeltingPoint": 1670},
{"Metal": "Cobalt", "MeltingPoint": 1495},
{"Metal": "Aluminum", "MeltingPoint": 660},
{"Metal": "Lead", "MeltingPoint": 327.5}
];
// Get max value to use as limiting factor on our gradient
var MaxMP = d3.max(MeltingPoints, function(d) {return d.MeltingPoint});
// simple counting variable
var ct = 0;
//define bar spacing, from top of one bar to top of next (y direction)
var spacing = 34;
//define a liner scale for bar bar length
var BarWidth = d3.scaleLinear()
.domain([0, MaxMP])
.range([0,300]);
// bind data to rectangles and add 'bars'
var bars = svg.selectAll("rect")
.data(MeltingPoints)
.enter()
.append("rect")
.attr("x", 200)
.attr("y", function () {ct++; return 85 + ct * spacing})
.attr("height", 30)
.attr("width", function(d) {return BarWidth(d.MeltingPoint)})
.attr("fill", ConstantGradient);
//reset counter
ct = 0;
var labels = svg.selectAll("text")
.data(MeltingPoints)
.enter()
.append("text")
.attr("x", 190)
.attr("y", function() {ct++; return 105 + ct * spacing})
.attr("text-anchor", "end")
.text(function(d) {return d.Metal + " (" + d.MeltingPoint + " C )"});
function ConstantGradient(d) {
//for each entry passed to this function a new gradient definition is
//created. A unique id is created based on input data and returned to
//the fill attribute in a url call.
var maxrgb = 230;
//This gradient controls the 'max' color reached in the linear scale
//by subtracting from the max rgb value we picked. ColorDiff is the amount
//to subtract from our max value to end at the proper place on the linear scale.
//This is found by multiplying our max value by the percent of the value's
//MeltingPoint to the max in the data set.
var ColorDiff = maxrgb*d.MeltingPoint/MaxMP;
var gradient = svg.append("defs")
.append("linearGradient")
.attr("id", "gradient" + d.Metal)
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%")
.attr("spreadMethod", "pad");
gradient.append("stop")
.attr("class", "left")
.attr("offset", "0%")
.attr("stop-color", d3.rgb(0,0,maxrgb))
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("class", "right")
.attr("offset", "100%")
.attr("stop-color", d3.rgb(ColorDiff+25,0,maxrgb-ColorDiff)) //+25 for more red
.attr("stop-opacity", 1);
return ("url(#gradient" + d.Metal + ")")
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment