Built with blockbuilder.org
forked from ninjakx's block: dashboard_dc_d3
license: mit |
Built with blockbuilder.org
forked from ninjakx's block: dashboard_dc_d3
<!DOCTYPE html> | |
<head> | |
<!-- <title>Test-Dashboard</title> --> | |
<style> | |
line { | |
stroke: #000000; | |
stroke-width: 1.5; | |
} | |
#interval { | |
float: right; | |
/* position: absolute; */ | |
} | |
select | |
{ | |
/*color: #ccc;*/ | |
} | |
option | |
{ | |
color: #000; | |
} | |
option:first-child | |
{ | |
background-color: #bdbdff; | |
} | |
</style> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.9/dc.min.css"> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.7/crossfilter.js"></script> | |
<script type="text/javascript" src="https://d3js.org/queue.v1.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.2.1/dc.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/reductio/1.0.0/reductio.js"></script> | |
</head> | |
<!-- column 3 for row --> | |
<div class="col-lg-6 col-md-6"> | |
<!-- row in column 3 --> | |
<div class="row"> | |
<!-- Bar Chart --> | |
<div class="col-lg-12 col-md-12"> | |
<div class="chart-wrapper"> | |
<div class="chart-stage"> | |
<div id="select-operation"> | |
<label><input type=radio name="operation" value="Confirmed" checked="true"> Confirmed</label> | |
<label><input type=radio name="operation" value="Active"> Active</label> | |
<label><input type=radio name="operation" value="Recovered"> Recovered</label> | |
<label><input type=radio name="operation" value="Death"> Death</label> | |
</div> | |
<div id="line-chart" class="svg-container"> | |
<select id="interval"></select> | |
<div class="chart-title"> | |
<span> | |
<strong>Line Types</strong> | |
</span> | |
<span> | |
<a href="javascript:composite.filterAll(); dc.redrawAll();" style="display:none;" class="reset">reset</a> | |
</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<body> | |
<script> | |
map_state = {"Andaman and Nicobar Islands": "AN", | |
"Andhra Pradesh": "AP", | |
"Arunachal Pradesh": "AR", | |
"Assam": "AS", | |
"Bihar": "BR", | |
"Chandigarh": "CG", | |
"Chhattisgarh": "CH", | |
"Daman and Diu" : "DD", | |
"Dadra and Nagar Haveli" : "DN", | |
"Delhi" : "DL", | |
"Goa" : "GA", | |
"Gujarat" : "GJ", | |
"Haryana" : "HR", | |
"Himachal Pradesh" : "HP", | |
"Jammu and Kashmir" : "HK", | |
"Jharkhand" : "JH", | |
"Karnataka" : "KA", | |
"Kerala" : "KL", | |
"Ladakh" : "LD", | |
"Lakshadweep" : "LK", | |
"Madhya Pradesh" : "MP", | |
"Maharashtra" : "MH", | |
"Manipur" : "MN", | |
"Meghalaya" : "MH", | |
"Mizoram" : "MZ", | |
"Nagaland" :"NL", | |
"Odisha" : "OD", | |
"Puducherry" : "PY", | |
"Punjab" : "PB", | |
"Rajasthan" : "RJ", | |
"Tamil Nadu" : "TN", | |
"Telangana" : "TS", | |
"Tripura" : "TR", | |
"Sikkim": "SK", | |
"Uttar Pradesh" : "UP", | |
"Uttarakhand" : "UK", | |
"West Bengal" : "WB", | |
} | |
var log = console.log; | |
Promise.all([ | |
d3.json("https://api.covid19india.org/data.json"), | |
d3.json("https://api.rootnet.in/covid19-in/unofficial/covid19india.org/statewise/history") | |
]).then(([data1,data2]) => { | |
log("==========>"); | |
log("data1:", data1); | |
log("data2:", data2); | |
}) | |
.catch(error => log('error', error)) | |
// queue() | |
// .defer(d3.json, 'https://api.covid19india.org/data.json') | |
// .defer(d3.json, 'https://api.rootnet.in/covid19-in/unofficial/covid19india.org/statewise/history') | |
// .await(makePlot); | |
// function makePlot(error, json1, json2){ | |
// log(json1); | |
// log(json2); | |
// }; | |
d3.json('https://api.rootnet.in/covid19-in/unofficial/covid19india.org/statewise/history').then(function(json_data) { | |
var data = json_data.data.history; | |
data.forEach(function(d,i){ | |
for (var j=0; j<d.statewise.length;j++) | |
{ | |
{ | |
d[map_state[d.statewise[j].state]] = d.statewise[j].confirmed; | |
} | |
} | |
}); | |
cf = crossfilter(data); // Main crossfilter objects | |
var cases_bar_d = cf.dimension(function(d) { | |
return new Date(d.day)}); | |
var cases_bar_g = cases_bar_d.group().reduce( | |
// add | |
(p, v) => { | |
v.statewise.forEach(({state, confirmed}) => p[state] = (p[state] || 0) + confirmed); | |
return p; | |
}, | |
// remove | |
(p, v) => { | |
v.statewise.forEach(({state, confirmed}) => p[state] -= confirmed); | |
return p; | |
}, | |
// init | |
() => ({}) | |
); | |
var active_cases_bar_g = cases_bar_d.group().reduce( | |
// add | |
(p, v) => { | |
v.statewise.forEach(({state, confirmed, recovered}) => p[state] = (p[state] || 0) + (confirmed - recovered) ); | |
return p; | |
}, | |
// remove | |
(p, v) => { | |
v.statewise.forEach(({state, confirmed, recovered}) => p[state] -= (confirmed - recovered)); | |
return p; | |
}, | |
// init | |
() => ({}) | |
); | |
var recovered_cases_bar_g = cases_bar_d.group().reduce( | |
// add | |
(p, v) => { | |
v.statewise.forEach(({state, recovered}) => p[state] = (p[state] || 0) + recovered ); | |
return p; | |
}, | |
// remove | |
(p, v) => { | |
v.statewise.forEach(({state, recovered}) => p[state] -= recovered); | |
return p; | |
}, | |
// init | |
() => ({}) | |
); | |
var death_cases_bar_g = cases_bar_d.group().reduce( | |
// add | |
(p, v) => { | |
v.statewise.forEach(({state, deaths}) => p[state] = (p[state] || 0) + deaths); | |
return p; | |
}, | |
// remove | |
(p, v) => { | |
v.statewise.forEach(({state, deaths}) => p[state] -= deaths); | |
return p; | |
}, | |
// init | |
() => ({}) | |
); | |
var prev = data[0].total.confirmed; | |
var daily_confirmed_g = cases_bar_d.group().reduce( | |
function (p, v) { | |
// if (prev !== v.total.confirmed) | |
// { | |
// prev = v.total.confirmed - prev; | |
// log("summmm:",prev); | |
// } | |
}, | |
function(p, v) { | |
}, | |
() => ({}) | |
); | |
const states = data[0].statewise.map(d => d.state); | |
var latest_data = data[data.length-1]; | |
var top_states =latest_data.statewise; | |
top_states = top_states.sort(function(a, b) { | |
return b.confirmed - a.confirmed; | |
}).slice(0,10).map(d => d.state); | |
// log("top_states:", top_states); | |
// log("cases_bar_g:", active_cases_bar_g.top(Infinity)); | |
const dateList = data.map(function (el) { | |
return (el.day); | |
}); | |
function find_max(state, case_type){ | |
var max_case = charts_cases_type[case_type].top(Infinity); | |
var max = 0, val; | |
for (var j=0; j<max_case.length;j++) | |
{ | |
val = max_case[j].value[state]; | |
if (max<=val){ | |
max = val; | |
} | |
} | |
return max; | |
} | |
var color = d3.scaleOrdinal(d3.schemeCategory10); | |
// log("max cases:", max_cases, max_cases); | |
// var colorScales =[ | |
// d3.scaleLinear() | |
// .interpolate(d3.interpolateHcl) | |
// .range(["#9AF768", "#F27A4D"]), | |
// d3.scaleLinear() | |
// //.domain([0,1]) | |
// .interpolate(d3.interpolateHcl) | |
// .range(["#112231","#3C769D"]) | |
// ]; | |
var colorScales =[ | |
d3.scaleOrdinal(d3.schemeCategory10), | |
d3.scaleOrdinal(d3.schemeSet3) | |
]; | |
const sDate = new Date(dateList[0]); | |
const eDate = new Date(dateList[dateList.length-1]); | |
var selected_state="top 10 states", selected_case_type = "confirmed"; | |
var charts_cases_type = {confirmed: cases_bar_g, active: active_cases_bar_g, recovered: recovered_cases_bar_g, deaths: death_cases_bar_g}; | |
var composite = dc.compositeChart("#line-chart"); | |
var linechart = dc.lineChart("#line-chart") | |
function comp_chart(case_type){ | |
var max_cases = find_max(top_states[0], case_type) | |
composite | |
.width(500) | |
.height(460) | |
.margins({left: 60, top: 20, right: 10, bottom: 100}) | |
.x(d3.scaleTime().domain([sDate,eDate])) | |
.y(d3.scaleLinear().domain([0,max_cases+100])) | |
.xUnits(d3.timeDays()) | |
.legend(dc.legend().x(70).y(40).itemHeight(13).gap(5)) | |
.renderHorizontalGridLines(true) | |
.brushOn(false) | |
.shareTitle(false) | |
.compose(top_states.map( | |
(state,i) => dc.lineChart(composite) | |
.dimension(cases_bar_d) | |
.group(charts_cases_type[case_type], state) | |
// .x(d3.scaleTime().domain([sDate,eDate])) | |
.valueAccessor(kv => kv.value[state]) | |
.colors(colorScales[0] | |
(Math.random())) | |
.x(d3.scaleTime().domain([sDate,eDate])) | |
.title(function(d) { return (d.key.toDateString() + "\n" + state + ': ' + d.value[state]) }) | |
)); | |
composite.renderlet(function(chart){ | |
chart.selectAll("g.x text") | |
.attr('transform', "rotate(30)") | |
.style('text-anchor','start') | |
.style('font-weight','bold'); | |
}); | |
composite | |
.on('pretransition.hideshow', legendToggle); | |
}; | |
function line_chart(state, case_type){ | |
var state_cases = find_max(state, case_type) | |
linechart | |
.width(500) | |
.height(460) | |
.margins({left: 60, top: 20, right: 10, bottom: 100}) | |
.dimension(cases_bar_d) | |
.group(charts_cases_type[case_type], state) | |
.valueAccessor(kv => kv.value[state]) | |
.colors(colorScales[0] | |
(Math.random())) | |
.legend(dc.legend().x(70).y(40).itemHeight(13).gap(5)) | |
.x(d3.scaleTime().domain([sDate,eDate])) | |
.y(d3.scaleLinear().domain([0,state_cases])) | |
.title(function(d) { return (d.key.toDateString() + "\n" + state + ': ' + d.value[state]) }) | |
.renderHorizontalGridLines(true) | |
.brushOn(false) | |
} | |
function drawLegendToggles(chart) { | |
chart.selectAll('g.dc-legend .dc-legend-item') | |
.style('opacity', function(d, i) { | |
var subchart = chart.select('g.sub._' + i); | |
var visible = subchart.style('visibility') !== 'hidden'; | |
return visible ? 1 : 0.2; | |
}); | |
} | |
function legendToggle(chart) { | |
chart.selectAll('g.dc-legend .dc-legend-item') | |
.on('click.hideshow', function(d, i) { | |
var subchart = chart.select('g.sub._' + i); | |
var visible = subchart.style('visibility') !== 'hidden'; | |
subchart.style('visibility', function() { | |
return visible ? 'hidden' : 'visible'; | |
}); | |
drawLegendToggles(chart); | |
}) | |
drawLegendToggles(chart); | |
} | |
comp_chart(selected_case_type); | |
var accessors = { | |
Confirmed: "confirmed", | |
Active: "active", | |
Recovered: "recovered", | |
Death: "deaths", | |
}; | |
d3.selectAll('#select-operation input') | |
.on('click', function() { | |
var ctype = accessors[this.value]; | |
selected_case_type = ctype; | |
switch(selected_state) | |
{ | |
case "top 10 states": | |
{ | |
var div = d3.selectAll("g.sub"); | |
div.style("display","none"); | |
comp_chart(ctype); | |
composite.redraw(); | |
break; | |
} | |
default: | |
{ | |
line_chart(selected_state, ctype); | |
linechart.redraw(); | |
// break; | |
} | |
} | |
}); | |
var intervals = {"Top 10 states" : "top 10 states"}; | |
states.forEach(function (state, index){ | |
intervals[state] = state; | |
}); | |
var defint = 'Top 10 states'; | |
d3.select('#interval').selectAll('option') | |
.data(Object.keys(intervals)) | |
.enter().append('option') | |
.text(function(d) { return d; }) | |
.attr('selected', function(d) { return d === defint ? '' : null; }); | |
function setup() { | |
var start_t = window.performance.now(); | |
var interval_name = d3.select('#interval').nodes()[0].value; | |
var interval = intervals[interval_name]; | |
selected_state = interval; | |
switch(interval_name) { | |
case 'Top 10 states': | |
comp_chart(selected_case_type); | |
composite.render(); | |
// dc.renderAll(); | |
break; | |
default: | |
line_chart(interval_name, selected_case_type); | |
linechart.render(); | |
// dc.renderAll(); | |
break; | |
} | |
}; | |
d3.select('#interval').on('change', function() { | |
setup(); | |
}); | |
dc.renderAll(); | |
}); | |
</script> | |
</body> |