Skip to content

Instantly share code, notes, and snippets.

@gordonwoodhull
Last active May 5, 2020 15:11
Show Gist options
  • Save gordonwoodhull/707fbf6e387dd63158fab2652d740b6a to your computer and use it in GitHub Desktop.
Save gordonwoodhull/707fbf6e387dd63158fab2652d740b6a to your computer and use it in GitHub Desktop.
dashboard_dc_d3
license: mit
<!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">&nbsp;Confirmed</label>
<label><input type=radio name="operation" value="Active">&nbsp;Active</label>
<label><input type=radio name="operation" value="Recovered">&nbsp;Recovered</label>
<label><input type=radio name="operation" value="Death">&nbsp;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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment