Public
Edited
Jan 8, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
updateBarsOld = (svg, data) => {
const rectWidth = 50
// ✨ OUR CODE HERE

const rect = d3.select(svg).selectAll('rect')
.data(data, d => d)

//exit
rect.exit().remove()

//enter
const enter = rect.enter().append('rect')
.attr('width', rectWidth)
.attr('fill', 'pink')
.attr('stroke', 'plum')
.attr('stroke-width', 2)

//enter+ipdate
enter.merge(rect)
.attr('x', (d, i) => i * rectWidth)
.attr('y', d => 100-d)
.attr('height' , d=> d)
}
Insert cell
Insert cell
updateBarsNew = (svg, data) => {
const rectWidth = 50

// ✨ OUR CODE HERE
const rect = d3.select(svg).selectAll('rect')
.data(data, d => d)
.join('rect')
.attr('x', (d, i) => i * rectWidth)
.attr('y', d => 100-d)
.attr('height' , d=> d)
.attr('width', rectWidth)
.attr('fill', 'pink')
.attr('stroke', 'plum')
.attr('stroke-width', 2)
}
Insert cell
Insert cell
{
const oldSVG = html`<svg height=100 style='overflow: visible' />`
const newSVG = html`<svg height=100 style='overflow: visible' />`
const code = html`<code />`
const button = html`<button>new data!</button>`
d3.select(button).on('click', d => {
// randomly generate an array of data
const data = _.times(_.random(3, 8), i => _.random(0, 100))

updateBarsOld(oldSVG, data)
updateBarsNew(newSVG, data)
// update div with new data array:
d3.select(code).text(JSON.stringify(data).replace(/\,/g, ', '))
})
return html`
<h4>old way:</h4>
${oldSVG}
<h4>new way:</h4>
${newSVG}
<p>
${button} ${code}
</p>
`
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const rectWidth = 50;
const svgHeight = 100;

const svg = html`<svg height=${svgHeight} style='overflow: visible' />`;
const code = html`<code />`;
const button = html`<button>new data!</button>`;

function updateBars() {
// select svg so that transition can be localized within selection
const t = d3.select("svg").transition().duration(1000);

// randomly generate an array of data
const data = _.times(_.random(3, 8), (i) => _.random(0, 100));

// ✨ YOUR CODE HERE
d3.select(svg)
.selectAll("rect")
.data(data, (d) => d)
.join(
(enter) => {
return enter.append("rect")
.attr("x", (d, i) => i * rectWidth)
.attr("height", 0)
.attr("y", svgHeight)
.attr('fill', 'pink')
.attr('stroke','plum')
.attr('stroke-width', 2)
},
(update) => update,
(exit) => {
exit.transition(t)
.attr("height", 0)
.attr("y", svgHeight)
}
)
.transition(t)
.attr("width", rectWidth)
.attr("x", (d, i) => i * rectWidth)
.attr("height", (d) => d)
.attr("y", (d) => svgHeight - d)

// update div with new data array:
d3.select(code).text(JSON.stringify(data).replace(/\,/g, ", "));
}

updateBars();
d3.select(button).on("click", updateBars);

return html`
${svg}
<p>
${button} ${code}
</p>
`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
filtered = _.filter(movies, d => {
// either the genre is in the filtered genres
return (_.includes(filteredGenres, d.genres[0]) ||
// OR the movie's genre isn't one of the top genres, and "Other" is toggled
(_.includes(filteredGenres, 'Other') && !_.includes(topGenres, d.genres[0]))) &&
// AND movie's pg rating is in filtered pg
_.includes(filteredPG, d.rated)
})
Insert cell
filteredFlowers = calculateData(filtered)
Insert cell
{
// this line is a little bit of Observable magic to make sure that every time
// our filter cells update, we use the existing SVG element instead of trashing it and creating a new one
// if you're working in your index.html, you'd create your svg element and select it as we did before
const element =
this || scrollSVG(html`<svg width=${width} height=${svgHeight}></svg>`);

const svg = d3.select(element).select("svg");

// create transition animation localized to svg selection
const t = svg.transition().duration(1000);

// ✨ YOUR CODE HERE
const g = svg
.selectAll("g")
.data(filteredFlowers, (d) => d.title)
.join(
(enter) => {
const g = enter
.append("g")
.attr("opacity", 0)
.attr("transform", (d) => `translate(${d.translate})`);

g.selectAll("path")
.data((d) =>
_.times(d.numPetals, (i) => {
return { rotate: i * (360 / d.numPetals), ...d };
})
)
.join("path")
.attr("transform", (d) => `rotate(${d.rotate})scale(${d.scale})`)
.attr("d", (d) => d.path)
.attr("fill", (d) => d.color)
.attr("stroke", (d) => d.color)
.attr("fill-opacity", 0.5)
.attr("stroke-width", 2);

g.append("text")
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.style("font-size", ".7em")
.text((d) => _.truncate(d.title, { length: 18 }));

return g;
},
(update) => update,
exit => {
exit.transition(t)
.attr('opacity', 0)
.remove()
}
)
.transition(t)
.attr("opcaity", 1)
.attr("transform", (d) => `translate(${d.translate})`);

return element;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more