Skip to content

Instantly share code, notes, and snippets.

@ninjakx
Created June 20, 2020 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninjakx/8d879d031312c80320eae76160b630da to your computer and use it in GitHub Desktop.
Save ninjakx/8d879d031312c80320eae76160b630da to your computer and use it in GitHub Desktop.
tip display
license: mit
<style>
.parent {
display: flex;
flex-wrap: wrap;
margin-left: 10vw;
margin-right: 10vw;
margin-top: 1%;
}
.child {
flex: 1 10 20%; /* explanation below */
margin-left: 1%;
margin-right: 1%;
height: 12.5vw;
background-color: blue;
}
#kpi {
padding: 10px 0;
/*display: flex;*/
flex-wrap: wrap;
}
#kpi-confirmed {
color: #f44334;
}
#kpi #kpi-active {
color: #1876d3;
}
#kpi #kpi-recovered {
color: #389e05;
}
#kpi #kpi-death {
color: #36484f;
}
/*#kpi .kpi-box {
}*/
#kpi .kpi-box {
padding: 0.8rem;
/*width: 210px;*/
line-height: 1.3rem;
/*height: 11rem;*/
display: block
}
#kpi .kpi-box {
background: #fff;
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
border-radius: 10px;
margin: 5px 5px;
}
#kpi .kpi-box .diff {
font-size: 1rem;
line-height: 1em;
font-weight: 700;
display: inline;
word-wrap: none;
}
#kpi .kpi-box .value {
font-size: 1.4rem;
font-weight: 800;
display: inline;
}
#kpi .kpi-box .label {
color: #000a12;
font-size: 0.9rem;
font-weight: 800;
margin-bottom: 0.5rem;
}
* {
box-sizing: border-box;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
width: 33.3%;
padding: 10px;
height: 25vw; /* Should be removed. Only for demonstration */
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/*#ui {
width:50% !important;
}
*/
.irs--round .irs-grid-text {
color: #002bff !important;
}
.irs--round .irs-grid-pol {
background-color: #6644df !important;
}
.irs--round.irs-with-grid {
/*height: 65px;*/
width: 93% !important;
left: 3% !important;
margin-bottom: 1%;
}
#interval {
width:100px;
}
</style>
<head>
<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 src="d3.slider.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.15.1/d3.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>
<!--Plugin CSS file with desired skin-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css"/>
<!--jQuery-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!--Plugin JavaScript file-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script>
<!--
<div class="range-slider">
<input type="text" class="js-range-slider" value="" />
</div>
<div class="extra-controls">
<input type="text" class="js-input" value="0" />
</div> -->
<!-- <div id="ui"></div> -->
<div class="parent" id="kpi">
<div class="child kpi-box" id="kpi-confirmed" value="confirmed" checked="true">
<div class="label" data-i18n="kpi-confirmed">Confirmed</div>
<div class="value"></div>
<div class="diff"></div>
<div class="description"></div>
<div id="daily_conf"></div>
<div class="chart-caption" data-i18n="confirmed-chart-caption">Daily new cases</div>
</div>
<div class="child kpi-box" id="kpi-active" value="active">
<div class="label" >Active</div>
<div class="value"></div>
<div class="diff"></div>
<div class="description"></div>
<div id="daily_actv"></div>
<div class="chart-caption" data-i18n="active-chart-caption">Daily new cases</div>
</div>
<div class="child kpi-box" id="kpi-recovered" value="recovered">
<div class="label">Recovered</div>
<div class="value"></div>
<div class="diff"></div>
<div class="description"></div>
<div id="daily_recov"></div>
<div class="chart-caption" data-i18n="recovered-chart-caption">Daily new cases</div>
</div>
<div class="child kpi-box" id="kpi-death" value="deaths">
<div class="label">Death</div>
<div class="value"></div>
<div class="diff"></div>
<div class="description"></div>
<div id="daily_dcsd"></div>
<div class="chart-caption" data-i18n="death-chart-caption">Daily new cases</div>
</div>
</div>
<div id="ui"></div>
<div class="row">
<div class="column" style="background-color:#aaa;">
<!-- <h2>Column 1</h2> -->
<div id="total_cases" class="svg-container">
<div class="chart-title">
<span style="font-size: 1.1em">
<strong>Total Cases</strong>
<br>
</span>
</div>
</div>
</div>
<div class="column" style="background-color:#bbb;">
<div id="line-chart" class="svg-container">
<div class="chart-title">
<span>
<strong>Total Cases Statewise</strong> <select id="interval"></select>
<br>
</span>
</div>
</div>
</div>
<div class="column" style="background-color:#ccc;">
<div id="line-chart2" class="svg-container">
<div class="chart-title">
<span>
<strong>Daily Cases</strong>
<br>
</span>
</div>
</div>
</div>
</div>
<script>
map_state = {"Andaman and Nicobar Islands": "AN",
"Andhra Pradesh": "AP",
"Arunachal Pradesh": "AR",
"Assam": "AS",
"Bihar": "BR",
"Chandigarh": "CG",
"Chhattisgarh": "CH",
"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;
const lang = 'en-US';
function dateToTS(date) {
return date.valueOf();
}
function tsToDate(ts) {
const d = new Date(ts);
return d.toLocaleDateString(lang, {
year: 'numeric',
month: 'long',
day: 'numeric',
});
}
function filterData(dt, from, to, formatReq) {
// log("--====--", dt, formatReq);
if (!formatReq) {
dt = dateToTS(new Date(dt));
}
else {
const parts = dt.split('/');
dt = new Date(
parts[1] + '-' + parts[0] + '-' + parts[2].split(' ')[0]
);
}
if (dt >= from && dt <= to) {
return true;
}
console.log("dt::::", dt, from, to);
}
var daily_conf = dc.lineChart("#daily_conf");
var daily_actv = dc.lineChart("#daily_actv");
var daily_recov = dc.lineChart("#daily_recov");
var daily_dcsd = dc.lineChart("#daily_dcsd");
var composite = dc.compositeChart("#line-chart");
// var composite2 = dc.compositeChart("#line-chart2");
var composite2 = dc.barChart("#line-chart2");
// var dailycase = dc.barChart("#line-chart2");
var linechart = dc.lineChart("#line-chart");
var total_chart = dc.compositeChart("#total_cases");
var total_line_chart = dc.lineChart("#total_cases");
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]) => {
var data = data1.cases_time_series;
var from = new Date(2020,0,31);
var to = new Date()
var co = 0, count=0;
// log("=============:::", data[data.length-1]);
for (var start = 0; start <= data.length-1; start++) {
var day = new Date(data[start].date+"2020");
// log("day:",day);
// date = day.toISOString().slice(0, 10);
date = day.toDateString().split(" ")
date = date[2]+"-"+date[1]+"-"+date[3]
// log("day:", day," date:", date);
if (new Date(date)<=new Date('2020-03-14'))
{
conf = parseInt(data[co]['totalconfirmed']);
recov = parseInt(data[co]['totalrecovered']);
dcsd = parseInt(data[co]['totaldeceased']);
actv = conf - recov - dcsd;
d_conf = parseInt(data[co]['dailyconfirmed']);
d_recov = parseInt(data[co]['dailyrecovered']);
d_dcsd = parseInt(data[co]['dailydeceased']);
d_actv = d_conf - d_recov - d_dcsd;
data[co] = {"day":date, "daily_confirmed": d_conf, "daily_recovered": d_recov, "daily_deceased": d_dcsd, "daily_active": d_conf-d_recov-d_dcsd};
data[co]['total'] = {"confirmed": conf, "recovered": recov, "deaths": dcsd, "active":actv };
statewise_arr = new Array(35);
for (var st=0; st<35; st++)
{
var state_name = Object.keys(map_state)[st];
statewise_arr[st] = ({'state': state_name, "confirmed": 0, "recovered": 0, "deaths": 0, "active": 0})
}
data[co]['statewise'] = statewise_arr;
count = count + 1;
}
else
{
data_add = data2.data.history[co-count+1];
conf = parseInt(data_add['total'].confirmed);
recov = parseInt(data_add['total'].recovered);
actv = parseInt(data_add['total'].active);
dcsd = parseInt(data_add['total'].deaths);
d_conf = parseInt(data[co]['dailyconfirmed']);
d_recov = parseInt(data[co]['dailyrecovered']);
d_dcsd = parseInt(data[co]['dailydeceased']);
d_actv = d_conf - d_recov - d_dcsd;
// log("===>:", data_add);
data[co] = {"day":date, "daily_confirmed": d_conf, "daily_recovered": d_recov, "daily_deceased": d_dcsd, "daily_active": d_conf-d_recov-d_dcsd};
data[co]['total'] = {"confirmed": conf, "recovered": recov, "deaths": dcsd, "active":actv };
var i =0;
statewise_arr = new Array();
for (var st=0; st<data_add['statewise'].length; st++)
{
statewise_arr[i] = (data_add['statewise'][st]);
i=i+1;
}
data[co]['statewise'] = statewise_arr;
}
co = co + 1 ;
}
// log("####:", data);
var latest_data = data[data.length-1];
var dateList = data.map(function (el) {
return new Date(el.day);
});
// log("--------->", dateList);
const startDate = new Date("2020-03-15");//new Date(Math.min.apply(null, dateList));
const endDate = new Date(Math.max.apply(null, dateList));
log("sdate,edate:", startDate, endDate);
const saveResult = function (datetime) {
const from = datetime['from'];
const to = datetime['to'];
log("from-to:", from, to);
const tsDataSliced = data.filter(function (d) {
return filterData(d.day, from, to, false);
});
stateline_chart(tsDataSliced);
log("sliced_data:", tsDataSliced);
return tsDataSliced;
};
$('#ui').ionRangeSlider({
skin: 'round',
type: 'double',
grid: true,
min: dateToTS(startDate),
max: dateToTS(endDate),
from: dateToTS(startDate),
to: dateToTS(endDate),
prettify: tsToDate,
// onStart: function (datatime) {
// saveResult(datatime)
// },
onChange: saveResult,
onFinish: saveResult,
})
;
data = data.filter(function (d) {
return filterData(d.day, dateToTS(startDate), dateToTS(endDate), false);
});
stateline_chart(data);
//
})
.catch(error => log('error', error))
function stateline_chart(data) {
// log("--->", data);
// var data = json_data.data.history;
cf = crossfilter(data); // Main crossfilter objects
// log("@@@@@@:", data);
var cases_bar_d = cf.dimension(function(d) {
// log("===>", d.day);
return new Date(d.day)});
var daily_cases_bar_g = cases_bar_d.group().reduce(
// add
(p, v) => {
p['dailyconfirmed'] = v.daily_confirmed || 0;
p['dailyrecovered'] = v.daily_recovered || 0;
p['dailydeaths'] = v.daily_deceased || 0;
p['dailyactive'] = v.daily_active || 0;
return p;
},
// remove
(p, v) => {
p['dailyconfirmed'] -= v.daily_confirmed;
p['dailyrecovered'] -= v.daily_recovered;
p['dailydeaths'] -= v.daily_deceased;
p['dailyactive'] -= v.daily_active;
return p;
},
// init
() => ({})
);
// log("!@#$:", daily_cases_bar_g.top(Infinity));
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(function({state, confirmed, recovered}) {
// log("%%%%%%%%:", state);
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 total_cases_bar_g = cases_bar_d.group().reduce(
// add
(p, v) => {
p['totalconfirmed'] = v.total.confirmed || 0;
p['totalrecovered'] = v.total.recovered || 0;
p['totaldeaths'] = v.total.deaths || 0;
p['totalactive'] = v.total.active || 0;
return p;
},
// remove
(p, v) => {
p['totalconfirmed'] -= v.total.confirmed;
p['totalrecovered'] -= v.total.recovered;
p['totaldeaths'] -= v.total.deaths;
p['totalactive'] -= v.total.active;
return p;
},
// init
() => ({})
);
const states = data[0].statewise.map(d => d.state);
var latest_data = data[data.length-1];
var top_states =latest_data.statewise;
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);
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};
$(document).ready(
function() {
$('#kpi-confirmed .value').text(latest_data.total.confirmed);
$('#kpi-confirmed .diff').html("(&nbsp;+"+latest_data.daily_confirmed+"&nbsp;)");
$('#kpi-active .value').text(latest_data.total.active);
$('#kpi-active .diff').html("(&nbsp;+"+latest_data.daily_active+"&nbsp;)");
$('#kpi-recovered .value').text(latest_data.total.recovered);
$('#kpi-recovered .diff').html("(&nbsp;+"+latest_data.daily_recovered+"&nbsp;)");
$('#kpi-death .value').text(latest_data.total.deaths);
$('#kpi-death .diff').html("(&nbsp;+"+latest_data.daily_deceased+"&nbsp;)");
}
);
// Drew SVG
var svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 230);
var width_conf = document.getElementById('kpi-confirmed').offsetWidth*0.85;
var height_conf = document.getElementById('kpi-confirmed').offsetHeight*0.60;
var width_total = document.getElementsByClassName('column')[0].offsetWidth;
var height_total = document.getElementsByClassName('column')[0].offsetHeight*0.85;
window.onresize = function(event) {
width_conf = document.getElementById("kpi-confirmed").offsetWidth*0.85;
height_conf = document.getElementById('kpi-confirmed').offsetHeight*0.55;
// log("323232:", width_conf, height_conf);
daily_conf.width(width_conf)
.height(height_conf);
daily_recov.width(width_conf)
.height(height_conf);
daily_actv.width(width_conf)
.height(height_conf);
daily_dcsd.width(width_conf)
.height(height_conf);
};
// log("height::::::", width_conf,width_conf*0.5, height_conf, height_conf*0.7)
function dailyconf()
{
daily_conf
.width(width_conf)
.height(height_conf)
.margins({top: 0, right: 0, bottom: -1, left: -1})
.transitionDuration(500)
.dimension(cases_bar_d)
.group(daily_cases_bar_g, "dailyconfirmed")
.valueAccessor(function(d) {
return d.value['dailyconfirmed'];})
.renderArea(true)
.elasticY(true)
.elasticX(true)
.colors("red")
.brushOn(false)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'), eDate]));
return daily_conf;
}
dailyconf();
function dailyrecov()
{
daily_recov.width(width_conf)
.height(height_conf)
.margins({top: 0, right: 0, bottom: -1, left: -1})
.transitionDuration(500)
.dimension(cases_bar_d)
.group(daily_cases_bar_g, "dailyrecovered")
.valueAccessor(function(d) {
return d.value['dailyrecovered'];})
.renderArea(true)
.elasticY(true)
.elasticX(true)
.colors("#389e05")
.brushOn(false)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'), eDate]));
}
dailyrecov();
function dailyactv()
{
daily_actv.width(width_conf)
.height(height_conf)
.margins({top: 0, right: 0, bottom: -1, left: -1})
.transitionDuration(500)
.dimension(cases_bar_d)
.group(daily_cases_bar_g, "dailyactive")
.valueAccessor(function(d) {
return d.value['dailyactive'];})
.renderArea(true)
.elasticY(true)
.elasticX(true)
.colors("#1876d3")
.brushOn(false)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'), eDate]));
}
dailyactv();
function dailydcsd()
{
daily_dcsd.width(width_conf)
.height(height_conf)
.margins({top: 0, right: 0, bottom: -1, left: -1})
.transitionDuration(500)
.dimension(cases_bar_d)
.group(daily_cases_bar_g, "dailydeaths")
.valueAccessor(function(d) {
return d.value['dailydeaths'];})
.renderArea(true)
.elasticY(true)
.elasticX(true)
.colors("#36484f")
.brushOn(false)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'), eDate]));
}
dailydcsd();
function daily_chart()
{
// log("^^^^^^^^^:", daily_cases_bar_g.all().length);
composite2
.width(width_total)
.height(height_total)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'),eDate]))
.xUnits(function(){ return 100} )
// .xUnits(daily_cases_bar_g.all().length * 0.8)
.margins({left: 55, top: 1, right: 30, bottom: 30})
.elasticX(true)
.elasticY(true)
.brushOn(false)
.yAxisLabel("Daily Cases")
.dimension(cases_bar_d)
.centerBar(true)
.ordinalColors(['#389e05', '#36484f', 'red'])
.group(daily_cases_bar_g, "dailyrecovered")
.valueAccessor(function(d) {
return d.value['dailyrecovered']})
.stack(daily_cases_bar_g, "dailydeaths", function(d) {return d.value['dailydeaths'];})
.stack(daily_cases_bar_g, "dailyactive", function(d) {return d.value['dailyactive'];})
.legend(dc.legend().x(75).y(15).gap(5).horizontal(false).legendText(function(d) {
return d.name;
}));
composite2.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
// composite2.on('preRedraw', function(chart) {
// chart.xUnits(chart.group().all().length * 0.8);
// });
// composite2.on("preRedraw", function (chart) {
// chart.rescale();
// });
}
daily_chart();
function daily_cases_type(case_type)
{
// log("case_type::::", case_type);
var cases_color = {'dailyconfirmed': 'red', 'dailyactive': '#1876d3', 'dailyrecovered': '#389e05', 'dailydeaths': '#36484f'};
composite2
.width(width_total)
.height(height_total)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'),eDate]))
.margins({left: 60, top: 1, right: 30, bottom: 30})
// .y(d3.scaleLinear().domain([0,1000]))
.brushOn(false)
.yAxisLabel("Daily Cases")
.dimension(cases_bar_d)
.centerBar(true)
.elasticX(true)
.elasticY(true)
.colors(cases_color[case_type])
.group(daily_cases_bar_g, case_type)
.valueAccessor(function(d) {
return d.value[case_type]})
.legend(dc.legend().x(75).y(15).gap(5).horizontal(false).legendText(function(d) {
return d.name;
}));
composite2.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
}
function total_cases_type(case_type)
{
// log("case_type:", case_type);
var cases_color = {'totalconfirmed': 'red', 'totalactive': '#1876d3', 'totalrecovered': '#389e05', 'totaldeaths': '#36484f'};
total_line_chart
.width(width_total)
.height(height_total)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'),eDate]))
.margins({left: 55, top: 1, right: 20, bottom: 30})
// .y(d3.scaleLinear().domain([0,1000]))
.brushOn(false)
.yAxisLabel("Total Cases")
.dimension(cases_bar_d)
.colors(cases_color[case_type])
// .centerBar(true)
.elasticY(true)
.elasticX(true)
// .colors(color[case_type])
.group(total_cases_bar_g, case_type)
.valueAccessor(function(d) {
return d.value[case_type]})
.legend(dc.legend().x(85).y(15).gap(5).horizontal(false).legendText(function(d) {
return d.name;
}));
total_line_chart.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
}
function total_cases_chart()
{
// log("------------>", width_total, height_total);
total_chart
.width(width_total)
.height(height_total)
.x(d3.scaleTime().domain([new Date('15 Mar 2020'),eDate]))
.margins({left: 60, top: 1, right: 30, bottom: 30})
.brushOn(false)
.yAxisLabel("Total Cases")
.dimension(cases_bar_d)
.elasticY(true)
.elasticX(true)
// .xUnits(dc.units.ordinal)
.compose([
dc.lineChart(total_chart)
.colors("red")
.group(total_cases_bar_g, "totalconfirmed")
.valueAccessor(function(d) {
return d.value['totalconfirmed']}),
dc.lineChart(total_chart)
.colors("#1876d3")
.group(total_cases_bar_g, "totalactive")
.valueAccessor(function(d) {
return d.value['totalactive']}),
dc.lineChart(total_chart)
.colors("#389e05")
.group(total_cases_bar_g, "totalrecovered")
.valueAccessor(function(d) {
return d.value['totalrecovered']}),
dc.lineChart(total_chart)
.colors("#36484f")
.group(total_cases_bar_g, "totaldeaths")
.valueAccessor(function(d) {
return d.value['totaldeaths']})
])
.legend(dc.legend().x(85).y(15).gap(5).horizontal(false).legendText(function(d) {
// log("**********:", d);
return d.name;
}));
// total_chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"))
total_chart.on('pretransition', function(chart){
chart.children().forEach(
child => child.selectAll('circle.dot')
.on('mousemove', null)
.on('mouseout', null)
);
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
// // remove hover events from dots
// total_chart.on('pretransition', chart => {
// chart.children().forEach(
// child => child.selectAll('circle.dot')
// .on('mousemove', null)
// .on('mouseout', null)
// );
// })
total_chart.on('postRender', chart => {
chart.svg().on('mousemove', () => {
// find closest data point
const x = chart.x().invert(d3.mouse(chart.svg().node())[0] - chart.margins().left),
xs = chart.children()[0].group().all().map(kv => kv.key),
right = d3.bisectLeft(xs, x);
// log("xonst x:", x);
let closest = right;
if(right >= xs.length)
closest = right - 1;
else if(right > 0) {
// see if point to the left is closer
if(x - xs[right-1] < xs[right] - x)
closest = right - 1;
}
console.log('closest', new Date(x), closest, xs[closest]);
chart.children().forEach(child => {
child.g().selectAll('circle.dot').each(function(d) {
if(d.x === xs[closest]) {
child._showDot(d3.select(this));
child.g().select('text.data-tip')
.attr('visibility', 'visible')
.attr('x', child.x()(d.x))
.attr('y', child.y()(d.y))
.text(tooltip_text(d.data))
} else
log("---->child-->", child);
child._hideDot(d3.select(this));
});
})
})
chart.svg().on('mouseout', () => {
chart.children().forEach(child => {
child.g().select('text.data-tip')
.attr('visibility', 'hidden')
child.selectAll('circle.dot').each(function(d) {
child._hideDot(d3.select(this));
});
})
})
chart.children().forEach(child => child.g()
.append('text')
.attr('class', 'data-tip')
.attr('fill', 'black')
.attr('alignment-baseline', 'top')
.attr('text-anchor', 'begin')
.attr('visibility', 'hidden')
)
});
// total_chart.yAxis().tickFormat(d3.format("s"));
}
// total_cases_type('totalconfirmed');
total_cases_chart();
total_chart.render();
function comp_chart_daily(){
var cases = ['dailyconfirmed', 'dailyrecovered', 'dailydeceased']
var cases_color = {'dailyconfirmed': 'red', 'dailyactive': '#1876d3', 'dailyrecovered': '#389e05', 'dailydeaths': '#36484f'};
// cases.map((case_type, i) => log("===>:", case_type, i));
composite2
.width(width_total)
.height(height_total)
// .ordinalColors(["#7FC97F","#BEAED4",'#FDC086'])
.x(d3.scaleTime().domain([sDate,eDate]))
.yAxisLabel("This is the Y Axis!")
.legend(dc.legend().x(70).y(40).itemHeight(13).gap(5))
.renderHorizontalGridLines(true)
.dimension(cases_bar_d)
.elasticX(true)
.elasticY(true)
.brushOn(false)
.shareTitle(false)
.compose(cases.map(
(case_type,i) => dc.lineChart(composite)
.dimension(cases_bar_d)
// .colors(cases_color[case_type])
.group(daily_cases_bar_g, "dailyconfirmed")
.valueAccessor(function(d) {
return d.value['dailyconfirmed']; })
));
composite.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
composite
.on('pretransition.hideshow', legendToggle);
};
function comp_chart(case_type){
top_states_res = top_states.sort(function(a, b) {
return b[case_type] - a[case_type];
}).slice(0,10).map(d => d.state);
var max_cases = find_max(top_states_res[0], case_type)
composite
.width(width_total)
.height(height_total)
.margins({left: 55, top: 1, right: 20, bottom: 30})
.yAxisLabel("Total Cases")
.x(d3.scaleTime().domain([new Date('15 Mar 2020'),eDate]))
.y(d3.scaleLinear().domain([0,max_cases*1.1]))
.xUnits(d3.timeDays())
.legend(dc.legend().x(85).y(15).itemHeight(13).gap(5))
.renderHorizontalGridLines(true)
.brushOn(false)
.elasticX(true)
.elasticY(true)
.shareTitle(false)
.compose(top_states_res.map(
(state,i) => dc.lineChart(composite)
.dimension(cases_bar_d)
.group(charts_cases_type[case_type], state)
.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.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
composite
.on('pretransition.hideshow', legendToggle);
};
function line_chart(state, case_type){
var cases_color = {'confirmed': 'red', 'active': '#1876d3', 'recovered': '#389e05', 'deaths': '#36484f'};
var state_cases = find_max(state, case_type)
linechart
.width(width_total)
.height(height_total)
.margins({left: 65, top: 1, right: 20, bottom: 30})
.dimension(cases_bar_d)
.group(charts_cases_type[case_type], state)
.valueAccessor(kv => kv.value[state])
.colors(cases_color[case_type])
.yAxisLabel("Total Cases")
.legend(dc.legend().x(80).y(15).itemHeight(13).gap(5))
.x(d3.scaleTime().domain([sDate,eDate]))
.y(d3.scaleLinear().domain([0,state_cases*1.1]))
.xUnits(d3.timeDays())
.title(function(d) { return (d.key.toDateString() + "\n" + state + ': ' + d.value[state]) })
.renderHorizontalGridLines(true)
.brushOn(false)
.elasticX(true)
.elasticY(true)
linechart.on('pretransition', function(chart){
chart.xAxis().ticks(8).tickFormat(d3.timeFormat("%d %b"));
chart.selectAll("g.x text")
.attr('transform', "rotate(30)")
.style('text-anchor','start')
.style('font-weight','bold');
chart.selectAll("g.y text")
.style('font-weight','bold');
});
}
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);
d3.selectAll('.kpi-box')//.select("kpi-confirmed")
.on('click', function() {
// log("%%%%%%%%:",this, d3.select(this).attr('value'));
d3.selectAll('.kpi-box').each(function() {
// log("->:",$(this))
$(this).css({
"box-shadow": "0px 2px 4px 0px rgba(0,0,0,0.2)"
});
})
$(this).css({
"box-shadow": "inset 0 1px 1px #dab6b6, 0 0 8px #da0707"
});
var ctype = d3.select(this).attr('value');
// log("ctype:" ,ctype);
selected_case_type = ctype;
daily_cases_type("daily"+ctype);
composite2.render();
total_cases_type("total"+ctype);
total_line_chart.margins({left: 70, top: 1, right: 30, bottom: 30})
total_line_chart.render();
switch(selected_state)
{
case "top 10 states":
{
var div = d3.selectAll("g.sub");
div.style("display","none");
comp_chart(ctype);
composite.margins({left: 65, top: 1, right: 20, bottom: 30})
composite.render();
break;
}
default:
{
line_chart(selected_state, ctype);
linechart.render();
}
}
});
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();
break;
default:
line_chart(interval_name, selected_case_type);
linechart.margins({left: 65, top: 1, right: 20, bottom: 30})
linechart.render();
break;
}
};
d3.select('#interval').on('change', function() {
setup();
});
dc.renderAll();
return ;
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment