Skip to content

Instantly share code, notes, and snippets.

@ninjakx
Last active June 7, 2020 13:05
Show Gist options
  • Save ninjakx/df926bd79540aa5986acb9faffab9b76 to your computer and use it in GitHub Desktop.
Save ninjakx/df926bd79540aa5986acb9faffab9b76 to your computer and use it in GitHub Desktop.
racing_bar_weird_unsigned_state
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
text{
/* position: absolute; */
font-size: 12px;
/* marrgin-left:10px; */
font-family: Open Sans, sans-serif;
}
text.title{
/* position: absolute;
top-left:10px; */
font-size: 24px;
font-weight: 500;
}
text.subTitle{
font-weight: 500;
fill: #777777;
}
text.caption{
font-weight: 400;
font-size: 14px;
fill: #777777;
}
text.label{
font-weight: 600;
}
text.valueLabel{
font-weight: 300;
}
text.yearText{
font-size: 40px;
font-weight: 700;
opacity: 0.25;
}
.tick text {
fill: #777777;
}
.xAxis .tick:nth-child(2) text {
text-anchor: start;
}
.tick line {
/* display: none; */
shape-rendering: CrispEdges;
stroke: #dddddd;
}
.tick line.origin{
stroke: #aaaaaa;
}
path.domain{
display: none;
}
#play-button {
position: absolute;
top: 140px;
left: 50px;
background: #f08080;
padding-right: 26px;
border-radius: 3px;
border: none;
color: white;
margin: 0;
padding: 0 12px;
width: 60px;
cursor: pointer;
height: 30px;
}
#play-button:hover {
background-color: #696969;
}
.ticks {
font-size: 10px;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
.track {
stroke: #000;
stroke-opacity: 0.3;
stroke-width: 10px;
}
.track-inset {
stroke: #dcdcdc;
stroke-width: 8px;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
stroke: transparent;
cursor: crosshair;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
}
</style>
</head>
<div id="vis">
<button id="play-button">Play</button>
</div>
<body>
<script>
// Feel free to change or delete any of the code you see in this editor!
// var n_case_range = [0,100, 500,1000,2000,3000,4000,5000];
var svg = d3.select("body").append("svg")
.attr("width", 600) // <-- state
.attr("height", 500);
var tickDuration = 500;
var top_n = 10;
var height = 500;
var width = 600; // <-- state
var padding_w_bar = 100;
const margin = {
top: 40,
right: 0,
bottom: 5,
left: 90
};
var svg1 = d3.select("#vis")
.append("svg")
.attr("width", 750)
.attr("height", 400);
let barPadding = (height-(margin.bottom+margin.top))/(top_n*5);
let title = svg.append('text')
.attr('class', 'title')
.attr('y', 20)
.attr('x', 80)
.html('Top 10 States');
let subTitle = svg.append("text")
.attr("class", "subTitle")
.attr("y", 35)
.attr('x', 85)
.html("Confirmed Cases");
let caption = svg.append('text')
.attr('class', 'caption')
.attr('x', width)
.attr('y', height-5)
.style('text-anchor', 'end');
// .html('Source: Interbrand');
var log = console.log;
d3.json('https://api.rootnet.in/covid19-in/unofficial/covid19india.org/statewise/history').then(function(json_data) {
let x, y, xAxis, yearText;
var line_ticks;
// var data = json_data.data.history[7].statewise;
var data1 = json_data.data.history
for (var start = 0; start <= data1.length-1; start++) {
var filtered = data1[start].statewise.filter(function(item) {
return !['State Unassigned', 'Dadra and Nagar Haveli and Daman and Diu', 'Daman and Diu', 'Dadra and Nagar Haveli'].includes( item.state);
});
log("%%%%:", filtered);
data1[start].statewise = filtered;
}
const dateList = data1.map(function (el) {
return (el.day);
});
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',
});
}
var formatDateIntoYear = d3.timeFormat("%d-%m-%Y");
var formatDate = d3.timeFormat("%d-%m-%Y");
var parseDate = d3.timeParse("%d-%m-%Y");
const sDate = new Date(dateList[0]);
const eDate = new Date(dateList[dateList.length-1]);
// log("sDate,eDate:", sDate, eDate);
startDate = sDate;
endDate = eDate;
var year = startDate;
var moving = false;
var currentValue = 0;
var targetValue = width;
var playButton = d3.select("#play-button");
var x1 = d3.scaleTime()
.domain([startDate, endDate])
.range([0, targetValue])
.clamp(true);
var slider = svg1.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + 100 + "," + 100 + ")");
slider.append("line")
.attr("class", "track")
.attr("x1", x1.range()[0])
.attr("x2", x1.range()[1])
.select(function() {
return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-inset")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-overlay")
.call(d3.drag()
.on("start.interrupt", function() { slider.interrupt(); })
.on("start drag", function() {
currentValue = d3.event.x;
update(x1.invert(currentValue));
})
);
slider.insert("g", ".track-overlay")
.attr("class", "ticks")
// .attr("transform", "translate(0," + 18 + ")")
.selectAll("text")
.data(x1.ticks())
.enter()
.append("text")
.attr("x", x1)
// .attr("y", 15)
// .attr("text-anchor", "middle")
// .attr("transform", "rotate(45)")
.attr("transform",function(d,i){return "translate(0,"+ (i) * (-35) +") rotate(45)";
log("==:", d,i )
})
.text(function(d) { return formatDateIntoYear(d); });
// .attr("transform", "rotate(45)");
var handle = slider.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 9);
var label = slider.append("text")
.attr("class", "label")
.attr("text-anchor", "middle")
.text(formatDate(startDate))
.attr("transform", "translate(0," + (-25) + ")")
var dataset;
var plot = svg.append("g")
.attr("class", "plot")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
dataset = data1;
drawPlot(dataset, true);
playButton
.on("click", function() {
var button = d3.select(this);
if (button.text() == "Pause") {
moving = false;
clearInterval(timer);
// timer = 0;
button.text("Play");
} else {
moving = true;
timer = setInterval(step, 100);
button.text("Pause");
}
})
function prepare(d) {
d.id = d.id;
d.date = parseDate(d.date);
return d;
}
function step() {
update(x1.invert(currentValue));
currentValue = currentValue + (targetValue/151);
if (currentValue > targetValue) {
moving = false;
currentValue = 0;
clearInterval(timer);
playButton.text("Play");
}
}
function update(h) {
// update position and text of label according to slider scale
handle.attr("cx", x1(h));
label
.attr("x", x1(h))
.text(formatDate(h));
// filter data set and redraw plot
var newData = dataset.filter(function(d) {
return new Date(d.day) <= h;
})
drawPlot(newData, false);
}
function drawPlot(data, initial_plot)
{
var yearSlice = data.slice(-1)[0].statewise;
var cDate = new Date(data.slice(-1)[0].day);
yearSlice.sort(function(a,b){
return d3.descending(a.confirmed, b.confirmed) ;})
.slice(0, top_n);
yearSlice.forEach((d,i) => {
d.colour = d3.hsl(Math.random()*360,0.75,0.75);
d.rank = i;
});
if (initial_plot==true)
{
x = d3.scaleLinear()
.domain([0,yearSlice[0].confirmed])
.range([margin.left, width-margin.right-65]);
y = d3.scaleLinear()
.domain([top_n, 0])
.range([height-margin.bottom, margin.top]);
xAxis = d3.axisTop()
.scale(x)
.ticks(width > 500 ? 5:2)
.tickSize(-(height-margin.top-margin.bottom))
.tickFormat(d => d.confirmed);
// d3.select("g").attr('axis xAxis', null);
// log("@@@@@@:", d3.selectAll("g.x.axis"))
line_ticks = svg.append('g')
.attr('class', 'axis xAxis')
.attr('transform', `translate(0, ${margin.top})`)
.call(xAxis)
.selectAll('.tick line')
.classed('origin', d => d == 0);
// log("line_ticks:", line_ticks);
// line_ticks.remove();
svg.selectAll('rect.bar')
.data(yearSlice, function(d)
{
// console.log("DDDDD:", d.state);
return d.state;
})
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', x(0)+1)
.attr('width', function(d)
{
// console.log("SSSSSSS:", d.confirmed, x(0), x(d.confirmed), x(d.confirmed)-x(0)); .html(d => d.name)
return x(d.confirmed)-x(0); }
)
.attr('y', function(d)
{
// console.log("ssss:", y(d.confirmed));
return y(d.rank)+30;
})
.attr('height', 40)
.style('fill', function(d){
// log("color:",d.colour);
return d.colour});
svg.selectAll('text.label')
.data(yearSlice, function(d)
{
// console.log("DDDDD:", d.state);
return d.state;
})
.enter()
.append('text')
.attr('class', 'label')
.attr('x', d => x(d.confirmed)+x(0))//+(d.state.length*10.6))
.attr('y', d => y(d.rank)+50)
.style('text-anchor', 'end')
.html(d => d.state);
svg.selectAll('text.valueLabel')
.data(yearSlice, function(d)
{
// console.log("DDDDD:", d.state);
return d.state;
})
.enter()
.append('text')
.attr('class', 'valueLabel')
.attr('x', d => x(d.confirmed)+20)
.attr('y', d => y(d.rank)+50)
.text(d => d3.format(',.0f')(d.confirmed));
yearText = svg.append('text')
.attr('class', 'yearText')
.attr('x', width-margin.right)
.attr('y', height-25)
.style('text-anchor', 'end')
.html(~~year);
// .call(halo, 10);
}
x.domain([0, yearSlice[0].confirmed]);
svg.select('.xAxis')
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.call(xAxis);
// log("@@@@@@@@@@:", yearSlice);
let bars = svg.selectAll('.bar').data(yearSlice, d => d.state);
bars
.enter()
.append('rect')
.attr('class', function(d){
return d.state;
})
.attr('x', x(0)+1)
.attr( 'width', d => x(d.confirmed)-x(0))
.attr('y', d => y(top_n+1)+5)
.attr('height', y(1)-y(0)-barPadding)
.style('fill', d => d.colour)
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5);
bars
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('width', d => x(d.confirmed)-x(0))
.attr('y', d => y(d.rank)+5);
bars
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('width', d => x(d.confirmed)-x(0))
.attr('y', d => y(top_n+1)+5)
.remove();
let labels = svg.selectAll('.label')
.data(yearSlice, d => d.state);
labels
.enter()
.append('text')
.attr('class', 'label')
.attr('x', d => x(d.confirmed)-8)
.attr('y', d => y(top_n+1)+5+((y(1)-y(0))/2))
.style('text-anchor', 'end')
.html(d => d.state)
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
labels
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.confirmed)-8)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
labels
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.confirmed)-8)
.attr('y', d => y(top_n+1)+5)
.remove();
let valueLabels = svg.selectAll('.valueLabel').data(yearSlice, d => d.state);
valueLabels
.enter()
.append('text')
.attr('class', 'valueLabel')
.attr('x', d => x(d.confirmed)+5)
.attr('y', d => y(top_n+1)+5)
.text(d => d3.format(',.0f')(d.confirmed))
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
valueLabels
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.confirmed)+5)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1)
.tween("text", function(d) {
let i = d3.interpolateRound(d.confirmed, d.confirmed);
return function(t) {
this.textContent = d3.format(',')(i(t));
};
});
valueLabels
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.confirmed)+5)
.attr('y', d => y(top_n+1)+5)
// log("-------->", yearSlice);
yearText.html(cDate.toDateString());
};
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment