D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
mwang102
Full window
Github gist
GFN Layer Cake
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Layer Cake </title> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js"></script> <style type="text/css"> h1 { font-family: Helvetica, sans-serif; font-size: 14px; font-weight: bold; } .area { stroke: none; } .area:hover { fill: yellow; } #backButton { cursor: pointer; } #backButton rect { fill: #ccc; } #backButton text { font-family: Helvetica, sans-serif; font-weight: bold; font-size: 14px; fill: black; } #backButton:hover rect { fill: red; } .unclickable { pointer-events: none; } </style> </head> <body> <script> let width = 800, height = 400, margin = {top: 50, right:50, left:100, bottom:50}; let dataset, xScale, yScale, xAxis, yAxis, area, svg; let stack = d3.stack() .order(d3.stackOrderDescending); let rowConvertor = (d,i)=>{ return { total:+d['value'], year:+d['year'], countryName: d['countryName'], builtupLand: +d['builtupLand'], carbon:+d['carbon'], cropLand: +d['cropLand'], fishingGround:+d['fishingGround'], forestProduct:+d['forestLand'], grazingLand:+d['grazingLand'] } } let keys = ['builtupLand','carbon','cropLand','fishingGround','forestProduct','grazingLand'] let key = (d)=>{ return d.key } let viewState = 0; svg = d3.select('body') .append('svg') .attr('width', width) .attr('height', height) d3.csv('analyze_trends_Data.csv', rowConvertor, (data)=>{ stack.keys(keys) let series = stack(data) xScale = d3.scaleTime() .domain([ d3.min(data, (d)=> {return d.year}), d3.max(data, (d)=>{ return d.year}) ]) .range([margin.left, width-margin.right * 2]) yScale = d3.scaleLinear() .domain([ 0, d3.max(data, (d)=>{ let sum = 0 for(let i=0; i<keys.length; i++){ sum += d[keys[i]]; } return sum }) ]) .range([height - margin.left, margin.left/2]) .nice() xAxis = d3.axisBottom() .scale(xScale) .ticks(10) .tickFormat(d3.format('d')) yAxis = d3.axisLeft() .scale(yScale) .ticks(5) area = d3.area() .x((d)=> { return xScale(d.data.year) }) .y0((d)=>{ return yScale(d[0]); }) .y1((d)=>{ return yScale(d[1]); }) svg.append('g') .attr('id', 'types') .selectAll('path') .data(series,key) .enter() .append('path') .attr('class', 'area') .attr('d', area) .attr('fill', (d,i)=>{ let color; switch(d.key){ case "builtupLand": color = d3.schemeCategory20[0]; break; case "carbon": color = d3.schemeCategory20[1]; break case "cropLand": color = d3.schemeCategory20[2]; break; case "fishingGround": color = d3.schemeCategory20[3]; break; case "forestProduct": color = d3.schemeCategory20[4]; break; case "grazingLand": color = d3.schemeCategory20[5]; break; } return color; }) .on('click', (d)=>{ viewState++ let type = d.key var thisTypeDataset = []; for (var i = 0; i < data.length; i++) { thisTypeDataset[i] = { year:data[i].year, builtupLand:0, carbon:0, cropLand:0, fishingGround:0, forestProduct:0, grazingLand:0, [type]:data[i][type] } } let typeStack = d3.stack() .order(d3.stackOrderDescending); typeStack.keys(keys) let thisTypeSeries = typeStack(thisTypeDataset); console.log(series,thisTypeSeries) var paths = d3.selectAll("#types path") .data(thisTypeSeries, key); var areaTransitions = paths.transition() .duration(1000) .attr('d', area ) //Update scale yScale.domain([ 0, d3.max(thisTypeDataset, function(d) { var sum = 0; sum += d[type]; return sum; }) ]); areaTransitions.transition() .delay(200) .on("start", function() { d3.select("g.y.axis") .transition() .duration(1000) .call(yAxis); }) .duration(1000) .attr("d", area); }) .append("title") .text(function(d,i) { return d.key; }); let backButton = svg.append('g') .attr("opacity", 1) .attr('id', 'backButton') .attr("transform", "translate(" + xScale.range()[0] + "," + yScale.range()[1] + ")"); backButton.append('rect') .attr('x', 0) .attr('x', 0) .attr('width', 70) .attr('height', 30) backButton.append('text') .attr('x', 7) .attr('y', 20) .html('← Back') svg.append('g') .attr('class', 'x axis') .attr("transform", "translate(0," + (height - margin.left) + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + (margin.left) + ",0)") .call(yAxis); backButton.on('click', ()=>{ if(viewState > 0){ //Re-bind type data and fade in types var typeAreaTransitions = d3.selectAll("g#types path") .data(series, key) .transition() .duration(250) .attr("opacity", 1) yScale.domain([ 0, d3.max(data, (d)=>{ let sum = 0 for(let i=0; i<keys.length; i++){ sum += d[keys[i]]; } return sum }) ]) typeAreaTransitions.transition() .duration(1000) .on("start", function() { d3.select("g.axis.y") .transition() .duration(1000) .call(yAxis); }) .attr("d", area) } }) }) </script> </body> </html>
https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js