Built with blockbuilder.org
Created
April 15, 2020 00:26
-
-
Save itsbvk/eca74dfeeb0c768274294f25daf5cc89 to your computer and use it in GitHub Desktop.
fresh block
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<style> | |
text{ | |
font-size: 16px; | |
font-family: Open Sans, sans-serif; | |
} | |
text.title{ | |
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: 64px; | |
font-weight: 700; | |
opacity: 0.25; | |
} | |
.tick text { | |
fill: #777777; | |
} | |
.xAxis .tick:nth-child(2) text { | |
text-anchor: start; | |
} | |
.tick line { | |
shape-rendering: CrispEdges; | |
stroke: #dddddd; | |
} | |
.tick line.origin{ | |
stroke: #aaaaaa; | |
} | |
path.domain{ | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
// Feel free to change or delete any of the code you see in this editor! | |
var svg = d3.select("body").append("svg") | |
.attr("width", 960) | |
.attr("height", 600); | |
var tickDuration = 500; | |
var top_n = 12; | |
var height = 600; | |
var width = 960; | |
const margin = { | |
top: 80, | |
right: 0, | |
bottom: 5, | |
left: 0 | |
}; | |
let barPadding = (height-(margin.bottom+margin.top))/(top_n*5); | |
let title = svg.append('text') | |
.attr('class', 'title') | |
.attr('y', 24) | |
.html('18 years of Interbrand’s Top Global Brands'); | |
let subTitle = svg.append("text") | |
.attr("class", "subTitle") | |
.attr("y", 55) | |
.html("Brand value, $m"); | |
let caption = svg.append('text') | |
.attr('class', 'caption') | |
.attr('x', width) | |
.attr('y', height-5) | |
.style('text-anchor', 'end') | |
.html('Source: Interbrand'); | |
let year = 2000; | |
d3.csv('brand_values.csv').then(function(data) { | |
//if (error) throw error; | |
console.log(data); | |
data.forEach(d => { | |
d.value = +d.value, | |
d.lastValue = +d.lastValue, | |
d.value = isNaN(d.value) ? 0 : d.value, | |
d.year = +d.year, | |
d.colour = d3.hsl(Math.random()*360,0.75,0.75) | |
}); | |
console.log(data); | |
let yearSlice = data.filter(d => d.year == year && !isNaN(d.value)) | |
.sort((a,b) => b.value - a.value) | |
.slice(0, top_n); | |
yearSlice.forEach((d,i) => d.rank = i); | |
console.log('yearSlice: ', yearSlice) | |
let x = d3.scaleLinear() | |
.domain([0, d3.max(yearSlice, d => d.value)]) | |
.range([margin.left, width-margin.right-65]); | |
let y = d3.scaleLinear() | |
.domain([top_n, 0]) | |
.range([height-margin.bottom, margin.top]); | |
let xAxis = d3.axisTop() | |
.scale(x) | |
.ticks(width > 500 ? 5:2) | |
.tickSize(-(height-margin.top-margin.bottom)) | |
.tickFormat(d => d3.format(',')(d)); | |
svg.append('g') | |
.attr('class', 'axis xAxis') | |
.attr('transform', `translate(0, ${margin.top})`) | |
.call(xAxis) | |
.selectAll('.tick line') | |
.classed('origin', d => d == 0); | |
svg.selectAll('rect.bar') | |
.data(yearSlice, d => d.name) | |
.enter() | |
.append('rect') | |
.attr('class', 'bar') | |
.attr('x', x(0)+1) | |
.attr('width', d => x(d.value)-x(0)-1) | |
.attr('y', d => y(d.rank)+5) | |
.attr('height', y(1)-y(0)-barPadding) | |
.style('fill', d => d.colour); | |
svg.selectAll('text.label') | |
.data(yearSlice, d => d.name) | |
.enter() | |
.append('text') | |
.attr('class', 'label') | |
.attr('x', d => x(d.value)-8) | |
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1) | |
.style('text-anchor', 'end') | |
.html(d => d.name); | |
svg.selectAll('text.valueLabel') | |
.data(yearSlice, d => d.name) | |
.enter() | |
.append('text') | |
.attr('class', 'valueLabel') | |
.attr('x', d => x(d.value)+5) | |
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1) | |
.text(d => d3.format(',.0f')(d.lastValue)); | |
let 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); | |
let ticker = d3.interval(e => { | |
yearSlice = data.filter(d => d.year == year && !isNaN(d.value)) | |
.sort((a,b) => b.value - a.value) | |
.slice(0,top_n); | |
yearSlice.forEach((d,i) => d.rank = i); | |
//console.log('IntervalYear: ', yearSlice); | |
x.domain([0, d3.max(yearSlice, d => d.value)]); | |
svg.select('.xAxis') | |
.transition() | |
.duration(tickDuration) | |
.ease(d3.easeLinear) | |
.call(xAxis); | |
let bars = svg.selectAll('.bar').data(yearSlice, d => d.name); | |
bars | |
.enter() | |
.append('rect') | |
.attr('class', d => `bar ${d.name.replace(/\s/g,'_')}`) | |
.attr('x', x(0)+1) | |
.attr( 'width', d => x(d.value)-x(0)-1) | |
.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.value)-x(0)-1) | |
.attr('y', d => y(d.rank)+5); | |
bars | |
.exit() | |
.transition() | |
.duration(tickDuration) | |
.ease(d3.easeLinear) | |
.attr('width', d => x(d.value)-x(0)-1) | |
.attr('y', d => y(top_n+1)+5) | |
.remove(); | |
let labels = svg.selectAll('.label') | |
.data(yearSlice, d => d.name); | |
labels | |
.enter() | |
.append('text') | |
.attr('class', 'label') | |
.attr('x', d => x(d.value)-8) | |
.attr('y', d => y(top_n+1)+5+((y(1)-y(0))/2)) | |
.style('text-anchor', 'end') | |
.html(d => d.name) | |
.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.value)-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.value)-8) | |
.attr('y', d => y(top_n+1)+5) | |
.remove(); | |
let valueLabels = svg.selectAll('.valueLabel').data(yearSlice, d => d.name); | |
valueLabels | |
.enter() | |
.append('text') | |
.attr('class', 'valueLabel') | |
.attr('x', d => x(d.value)+5) | |
.attr('y', d => y(top_n+1)+5) | |
.text(d => d3.format(',.0f')(d.lastValue)) | |
.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.value)+5) | |
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1) | |
.tween("text", function(d) { | |
let i = d3.interpolateRound(d.lastValue, d.value); | |
return function(t) { | |
this.textContent = d3.format(',')(i(t)); | |
}; | |
}); | |
valueLabels | |
.exit() | |
.transition() | |
.duration(tickDuration) | |
.ease(d3.easeLinear) | |
.attr('x', d => x(d.value)+5) | |
.attr('y', d => y(top_n+1)+5) | |
.remove(); | |
yearText.html(~~year); | |
if(year == 2018) ticker.stop(); | |
year = d3.format('.1f')((+year) + 0.1); | |
},tickDuration); | |
}); | |
const halo = function(text, strokeWidth) { | |
text.select(function() { return this.parentNode.insertBefore(this.cloneNode(true), this); }) | |
.style('fill', '#ffffff') | |
.style( 'stroke','#ffffff') | |
.style('stroke-width', strokeWidth) | |
.style('stroke-linejoin', 'round') | |
.style('opacity', 1); | |
} | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment