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> |