makeChart = (dataset) => {
dataset = [...dataset];
dataset.sort((a,b) => b.downloads - a.downloads);
const w = 600;
const h = dataset.length * 24;
const svg = d3.create('svg')
.attr('width', w)
.attr('height', h);
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d => d.downloads)])
.rangeRound([0, w - 100]);
const yScale = d3.scaleBand()
.domain(dataset.map(d => d.app_name))
.rangeRound([20, h - 20]);
const colorScale = d3.scaleLinear()
.domain(xScale.domain())
.range(['#88d', '#ccf']);
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
const xAxisGroup = svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(80, ${h - 20})`)
.call(xAxis);
const yAxisGroup = svg.append('g')
.attr('class', 'axis-left1')
.attr('transform', `translate(80,0)`)
.call(yAxis);
const updateChartType = (newType) => {
console.log(newType);
// TODO
// Depending on newType
// update the chart by:
// 1. re-sorting the dataset
dataset.sort((a, b) => b[newType] - a[newType]);
// 2. update xscale domain
xScale.domain([0, d3.max(dataset, d => d[newType])]);
// 3. update yscale domain
yScale.domain(dataset.map(d => d.app_name));
// 4. Modifying the update parameter of .join, use transition to then
// update x,y, and width of bars
svg.selectAll('rect')
.data(dataset, d => d.app_name)
.join(
enter => enter.append('rect')
.attr('x', 80)
.attr('y', d => yScale(d.app_name))
.attr('width', 0) // Set initial width to 0 for the enter transition
.attr('height', 18)
.attr('fill', d => colorScale(d[newType]))
.transition()
.duration(500)
.attr('width', d => xScale(d[newType])),
update => update
.transition()
.duration(500)
.attr('x', 80)
.attr('y', d => yScale(d.app_name))
.attr('width', d => xScale(d[newType]))
.attr('height', 18)
.attr('fill', d => colorScale(d[newType]))
);
// After that, alway update xAxis scale, xAxisGroup with xAxis (call), and same for yAxis scale and yAxisGroup
xAxis.scale(xScale);
xAxisGroup.transition().call(xAxis);
yAxis.scale(yScale);
yAxisGroup.transition().call(yAxis);
svg.selectAll('rect')
.data(dataset, d => d.app_name)
.join(
enter => enter.append('rect')
.attr('x', 80)
.attr('y', d => yScale(d.app_name))
.attr('width', d => xScale(d.downloads))
.attr('height', 18)
.attr('fill', d => colorScale(d.downloads)),
// UPDATE the below
update => update
);
};
updateChartType('downloads');
const typeSelector = html`
<select id='chartType'>
<option value="downloads">Downloads</option>
<option value="average_rating">Popularity</option>
<option value="thirty_day_keep">Retention</option>
</select>
`;
d3.select(typeSelector).on('change', () => {
updateChartType(typeSelector.value);
});
return html`
<div class='chart-div'>
<label>Chart Type:</label>
${typeSelector}
${svg.node()}
</div>
`;
}