chart_small = (data_s) => {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");
const g = svg
.attr('preserveAspectRatio', 'xMidYMid')
.append('g')
.attr('transform', `translate(${margin.left + margin.right}, ${margin.top - margin.bottom})`)
const countries = g.selectAll('.countries')
.data(data_s)
.enter().append('g')
.attr('class', 'country-groups');
const x_column = ({column}) => column * 300
const y_column = ({row}) => row * 330
const colorscale=d3.scaleOrdinal()
.domain(['enrl_popu','unsd_popu','unpd_popu'])
.range(d3.schemeCategory10)
const canvas=countries.append('g').attr('class','canvas').attr('transform', d => `translate(${x_column(d)}, ${y_column(d)})`)
const header=canvas.append('g').attr('class','header').attr('transform','translate(100,0)')
const lines=canvas.append('g').attr('class','linechart').attr('transform','translate(0,115)')
header.append('g').attr('class','key label').attr('text-anchor', 'middle')
.append('text').attr('x',0).attr('y',30)
.text(d=>d.key).attr('font-size',12).attr('font-weight','bold')
header.append('g').attr('class','year label').append('text')
.attr('x',0).attr('y',42).attr('text-anchor', 'middle')
.text(d=>('Enrl&UNPD data: '+d['enrl_year']+' | UNSD data: ' +d['unsd_year'])).attr('font-size',8)
lines.append('g').attr('class','xAxis')
.each(function(d, i){
const mapX = d3.scalePoint() .domain(d.age_range).range([0,200])
const x_axis = d3.axisBottom(mapX).ticks(width / 80).tickSizeOuter(0)
d3.select(this).attr("transform", `translate(0,200)`)
.call(x_axis)
})
lines.append('g').attr('class','yAxis')
.each(function(d, i){
const mapY = d3.scaleLinear()
.domain(d.popu_range).nice()
.range([200,0])
const y_axis = d3.axisLeft(mapY).tickFormat(d3.format(".3s")).tickSizeInner(2)
d3.select(this).call(y_axis)
})
// lines.append('g').attr('class','area')
lines.append("g").attr('class','area1')
lines.append("g").attr('class','area2')
lines.append("g").attr('class','clip1')
lines.append("g").attr('class','clip2')
lines.select('.clip1').selectAll('clipPath')
.data(d=>[d.data[0][0]])
.join("clipPath")
.attr("id", d=>d[0].ISO)
.append("path")
.attr("d", d=>{
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const area = d3.area()
.x((o) => mapX(o.age))
.y0(0)
.y1(o => mapY(o.popu))
return area(d)
});
lines.select('.clip2').selectAll('clipPath')
.data(d=>[d.data[0][1]])
.join("clipPath")
.attr("id", d=>(d[0].ISO+'2'))
.append("path")
.attr("d", d=>{
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const area = d3.area()
.x((o,i) => mapX(o.age))
.y0(0)
.y1(o => mapY(o.popu))
return area(d)
});
lines.select('.area1')
.selectAll("path")
.data(d=>[d.data[0][1]])
// .attr("clip-path", 'url(#Malawi)')
.join("path")
.attr("fill", d=> {return colorscale('unsd_popu')})
.attr("clip-path", d=>"url(#"+d[0].ISO+")")
.style('opacity',0.2)
.attr("d", d=>{
// console.log(d[0],d,'1')
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const area = d3.area()
.x((o,i) => mapX(o.age))
.y0(200)
.y1(o => mapY(o.enrl_base))
return area(d)
});
lines.select('.area2')
.selectAll("path")
.data(d=>[d.data[0][1]])
.join("path")
.attr("fill", d=> {return colorscale('unpd_popu')})
.attr("clip-path", d=>"url(#"+d[0].ISO+"2)")
.style('opacity',0.2)
.attr("d", d=>{
// console.log(d[0],d,'1')
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const area = d3.area()
.x((o,i) => mapX(o.age))
.y0(200)
.y1(o => mapY(o.enrl_base))
return area(d)
});
// lines.select('.area')
// .selectAll("path")
// .data(d=>d.data[0])
// .join("path")
// .attr("fill", d=> {return colorscale(d[0].source)})
// .attr('fill-opacity',0.3)
// .attr("d", d=>{
// const country=d[0].Country
// const mapX = d3.scaleLinear().domain([d[0].start,d[0].end])
// .range([0,200])
// const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
// const mapY = d3.scaleLinear()
// .domain(popu_range).nice()
// .range([200,0])
// const area = d3.area()
// .defined(o => {return (o.enrl_base-o.popu)>0})
// .x((o,i) => mapX(o.age))
// .y0(o=> mapY(o.enrl_base))
// .y1(o => mapY(o.popu))
// return area(d)
// });
lines.append("g").attr('class','light')
canvas.select('.light')
.selectAll("path")
.data(d=>d.data[1])
.join("path")
.attr("d", (d,i) => {
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const line = d3.line()
.defined(o => o.popu!=null)
.x(o=>mapX(o.age))
.y(o=>mapY(o.popu))
return line(d)
})
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
lines.append("g").attr('class','solid')
canvas.select('.solid')
.selectAll("path")
.data(d=>d.data[0])
.join("path")
.attr("d", (d,i) => {
const country=d[0].Country
const mapX = d3.scalePoint().domain(d3.range(d[0].start,d[0].end+1))
.range([0,200])
const popu_range = data_small.filter(d=>d.key==country)[0].popu_range
const mapY = d3.scaleLinear()
.domain(popu_range).nice()
.range([200,0])
const line = d3.line()
.defined(o => o.popu!=null)
.x(o=>mapX(o.age))
.y(o=>mapY(o.popu))
// console.log(d,line(d))
return line(d)
})
.attr("fill", "none")
.attr("stroke", d=> {return colorscale(d[0].source)})
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
const margin2 = ({ top: 40, right: 50, bottom: 70, left: 50 })
// const data=data_single(country)
// const ages=data[2].filter(d=>d.source=='unpd_popu').map(d=>d.age)
const w = 150
const gridSize = 18
// Math.floor(w /(ages.length+1) )
const h = gridSize * 2 + margin2.top + margin2.bottom
const heatmap=canvas.append('g').attr('class','heatmap').attr('transform','translate(0,50)')
heatmap.selectAll('rect')
.data(d=> {
return d.value.filter(o=>o.source!='enrl_popu')})
.join("rect")
.attr("x", (d) => {
// console.log(d,d.age,d.source)
return (d.age-d.start) * 200/(d.end-d.start)})
.attr("y", d => (d.source=='unsd_popu'?0:1)* 200/(d.end-d.start))
.attr("width", d=> 200/(d.end-d.start))
.attr("height",d=> 200/(d.end-d.start))
// .style("text-anchor", "middle")
.attr('transform',d=>'translate('+(-100/(d.end-d.start))+',0)')
.attr("fill", d => {
const country= d.Country
const percents = data_small.filter(d=>d.key==country)[0].value.map(o=>o.percent).filter(d=>!isNaN(d))
const extent = d3.extent(percents)
let color= function() {}
if (extent[0]<0){
color = d3.scaleDiverging()
.domain([extent[0], 0, extent[1]])
.range([0,0.5,1])
}
else{
color = d3.scaleLinear()
.domain([0, extent[1]])
.range([0.5,1])
}
if (!isNaN(d.percent)){
return d3.interpolateRdYlBu(color(d.percent))
}else{
return 'white'
}
// console.log(color(d.percent))
// return d3.interpolateRdBu(color(d.percent))
})
.attr("stroke", "#e2e2e2")
// .append("title")
// .text(d => d.percent)
heatmap.selectAll(".source")
.data(['unsd','unpd','age'])
.join("text")
.text(d => d)
.classed("source", true)
.attr("x", 0)
.attr("y", (d, i) => i * gridSize)
.attr("text-anchor", "end")
.attr("transform", "translate(-10," + gridSize / 1.5 + ")")
.attr('font-size',9)
// canvas.append('g')
// .attr('class','area')
// canvas.select('.area')
// .selectAll("path")
// .data(d=>d.data[0])
// .join("path")
heatmap.selectAll(".age")
.data(d=>d.value.filter(o=>o.source=='unpd_popu'))
.join("text")
.text(d => d.age)
.classed("age", true)
.attr("x", d=>(d.age-d.start) * 200/(d.end-d.start))
.attr("y", d=>200/(d.end-d.start)*2.6)
.attr("text-anchor", "middle")
.attr('font-size',9)
heatmap.append('g').attr('class','label_heat')
heatmap.select(".label_heat").selectAll('text')
.data(d=>d.value.filter(d=>d.source!='enrl_popu'))
.join("text")
.text(d => {
if (!isNaN(d.percent)){
return (d.percent).toFixed(0)}else{return 'm'}})
.classed("label", true)
.attr("x", d => (d.age-d.start+0.5) * 200/(d.end-d.start))
.attr("y", d =>(d.source=='unsd_popu'?0:1) *200/(d.end-d.start))
.attr('transform',d=>'translate('+(-100/(d.end-d.start))+','+100/(d.end-d.start)+')')
.attr("text-anchor", "middle")
.attr('fill',(d)=>{
const country= d.Country
const percents = data_small.filter(d=>d.key==country)[0].value.map(o=>o.percent).filter(d=>!isNaN(d))
const extent = d3.extent(percents)
let color= function() {}
if (extent[0]<0){
color = d3.scaleDiverging()
.domain([extent[0], 0, extent[1]])
.range([0,0.5,1])
}
else{
color = d3.scaleLinear()
.domain([0, extent[1]])
.range([0.5,1])
}
const scale=color(d.percent)
if ((scale>0.75)|(scale<0.25)){return 'white'}
else{return 'black'}}).attr('font-size',8)
// svg.call(hover, path);
return svg.node();
}