D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
mwang102
Full window
Github gist
GFN Compare Countries
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> Compare Countries</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js"></script> <style> #formPanel{ padding: 10px; float:left; width:150px; height: 487px; background:lightblue; } #svg{ float:left; background:#c2b280; } </style> </head> <body> <div id="svg"></div> <div id="formPanel"> <form onsubmit="return addData()" class="my-form"> Country Name:<br> <input type="text" id="country" value="Lala Land" required><br> Carbon:<br> <input type="text" id="carbon" value="300000000" required><br> Fishing Grounds:<br> <input type="text" id="fishingGround" value="600000000" required><br> Crop Land:<br> <input type="text" id="cropLand" value="500000000" required><br> Built-up Land:<br> <input type="text" id="builtupLand" value="800000000" required><br> Forest Products:<br> <input type="text" id="forestProduct" value="200000000" required><br> Grazing Land:<br> <input type="text" id="grazingLand" value="100000000" required><br> <input type="submit" value="Add Country"> </form> <button onclick="reorder()"> Reorder</button> </div> <script type="text/javascript"> let width = 700, height = 500, margin = {left: 100, bottom: 100, right: 50, top: 50 }; let svg = d3.select('#svg') .append('svg') .attr('width', width) .attr('height', height) let dataset, xScale, yScale, xAxis, yAxis, series, stack, groups, rects; let colors = d3.scaleOrdinal(d3.schemeCategory10); let createInitial = (data,keys)=>{ let obj = {}, array = []; for(let i = 0 ; i<Object.keys(data).length; i++){ for(let j=0; j<keys.length; j++){ if(keys[j] == Object.keys(data)[i]){ array.push(data[keys[j]]) } } } obj['country'] = data.countryName obj['value'] = array; obj['total'] = data.total; return obj } let stackedData = (data,keys) => { let mapData = []; for(let i = 0; i<data.length; i++){ mapData.push(createInitial(data[i], keys)) } return mapData.map(function(d){ let y0=0 return { value:d.value.map(function(d){ return { y0:y0, y1: y0+=d } }), total: d.total } }) } let rowConvertor = (d,i) =>{ return { total:+d['Total'], countryName: d['Country Name'], year:+d['year'], builtupLand: +d['Built-up Land'], carbon:+d['Carbon'], cropLand: +d['Cropland'], fishingGround:+d['Fishing Grounds'], forestProduct:+d['Forest Products'], grazingLand:+d['Grazing Land'] } } let sortOrder = false; let keys = ['builtupLand', 'carbon', 'cropLand', 'fishingGround', 'forestProduct', 'grazingLand'] d3.csv('stacked_bar_data.csv', rowConvertor, (data)=>{ dataset = data dataset.sort((a,b)=>{ return b.total - a.total}); //Set up scales xScale = d3.scaleBand() .domain(d3.range(data.length)) .range([margin.left, width]) .paddingInner(0.05) yScale = d3.scaleLinear() .domain([0, d3.max(data, function(d) { return d.builtupLand + d.carbon + d.cropLand + d.fishingGround + d.forestProduct + d.grazingLand; }) ]) .range([height-margin.bottom, margin.top]); xAxis = d3.axisBottom() .scale(xScale) yAxis = d3.axisLeft() .scale(yScale) .ticks(10) let groups = svg.selectAll('g') .data(stackedData(data,keys)) .enter() .append('g') .attr('class', 'groups') .attr('transform', (d,i)=>{ return 'translate(' + (margin.left+ (i * ((width-margin.left)/data.length))) + ',0)' }) let rects = groups.selectAll("rect") .data(function(d) { return d.value; }) .enter() .append("rect") .attr("y", function(d) { return yScale(d.y1); }) .attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); }) .attr("width", xScale.bandwidth()) .style('fill', (d,i)=>{ return colors(i) }) svg.append('g') .attr('class', 'x axis') .attr('transform', 'translate(0,' + (height-margin.bottom) + ')') .call(xAxis) .selectAll("text") .text((d,i)=>{ return data[i].countryName }) .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", "-.55em") .attr("transform", "rotate(-45)" ); svg.append('g') .attr('class', 'y axis') .attr("transform", "translate(" +margin.left + ", 0)") .call(yAxis) }) function reorder(){ sortOrder = !sortOrder //flips sorting order if(sortOrder){ dataset.sort((a,b)=>{ return a.total - b.total}) }else{ dataset.sort((a,b)=>{ return b.total - a.total}) } svg.selectAll('.groups') .sort((a,b)=>{ if(sortOrder){ return d3.ascending(a.total, b.total); }else{ return d3.ascending(b.total, a.total) } }) .transition() .duration(1000) .attr('transform', (d,i)=>{ return 'translate(' + (margin.left+ (i * ((width-margin.left)/dataset.length))) + ',0)' }) svg.select('.x.axis') .selectAll('text') .transition() .duration(500) .text((d,i)=>{ return dataset[i].countryName }) .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", "-.55em") .attr("transform", "rotate(-45)" ); /* .attr('transform', (d,i)=>{ console.log(d,i) return 'translate(0,0)' }) */ } function addData(){ let entryData = { total: 0, countryName: document.getElementById('country').value, builtupLand: +document.getElementById('builtupLand').value, carbon: +document.getElementById('carbon').value, cropLand: +document.getElementById('cropLand').value, fishingGround: +document.getElementById('fishingGround').value, forestProduct: +document.getElementById('forestProduct').value, grazingLand: +document.getElementById('grazingLand').value } for(key in entryData){ if(key != 'countryName'){ entryData.total += +entryData[key] } } dataset.push(entryData) xScale.domain(d3.range(dataset.length)); yScale.domain([0, d3.max(dataset, function(d) { return d.builtupLand + d.carbon + d.cropLand + d.fishingGround + d.forestProduct + d.grazingLand; }) ]) svg.selectAll('.groups') .attr('transform', (d,i)=>{ return 'translate(' + (margin.left+ (i * ((width-margin.left)/dataset.length))) + ',0)' }) .selectAll("rect") .attr("width", xScale.bandwidth()) groups = svg.selectAll('.groups') .data(stackedData(dataset,keys)) groups.enter() .append('g') .attr('class', 'groups') .attr('transform', (d,i)=>{ return 'translate(' + (margin.left+ (i * ((width-margin.left)/dataset.length))) + ',0)' }) .selectAll('rect') .data((d)=> { return d.value }) .enter() .append("rect") .transition() .duration(500) .attr("y", function(d) { return yScale(d.y1); }) .attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); }) .attr("width", xScale.bandwidth()) .style('fill', (d,i)=>{ return colors(i) }) svg.select('.x.axis') .transition() .duration(500) .call(xAxis) .selectAll('text') .text((d,i)=>{ return dataset[i].countryName }) .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", "-.55em") .attr("transform", "rotate(-45)" ); svg.select('.y.axis') .transition() .duration(500) .call(yAxis) return false } </script> </body> </html>
https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js