Published
Edited
Sep 13, 2020
8 stars
Insert cell
Insert cell
md `## A Single Petal`
Insert cell
petalPath = 'M 0,0 C -10,-20 -20,-30 0,-50 C 20,-30 10,-20 0,0';
Insert cell
html `<svg width="${petalSize}" height="${petalSize}"><path d="${petalPath}"></svg>`
Insert cell
petalPath2 = 'M 0,0 C -10,-10 -30,-50 0,-50 C 30,-50 10,-10 0,0';
Insert cell
html `<svg width="${petalSize}" height="${petalSize}"><path transform="translate(25,50)" d="${petalPath2}"></svg>`
Insert cell
petalPath3 = 'M 0,0 C -10,-20 -20,-30 0,-50 C 20,-30 10,-20 0,0';
Insert cell
html `<svg width="${petalSize}" height="${petalSize}"><path transform="translate(25,50)" d="${petalPath3}"></svg>`
Insert cell
petalPath4 = 'M0,0 C-1,-15 -25,-30 -10,-50 C-10,-40 10,-40 10,-50 C25,-30 1,-15 0,0'
Insert cell
html `<svg width="${petalSize}" height="${petalSize}"><path transform="translate(25,50)" d="${petalPath4}"></svg>`
Insert cell
petalSize = 50;
Insert cell
md `## Data!

We clean up the data inside our Utils but should probably do that here...`
Insert cell
data=d3.json('https://raw.githubusercontent.com/sxywu/filmflowers/master/movies.json')
// use lodash to turn our object into an array!
.then(data => _.values(data));
Insert cell
md `## Draw a Single Flower with Data`
Insert cell
d = data[12]
Insert cell
d.Rated
Insert cell
{
if (d.Rated === "G") return petalPath
else if (d.Rated === "PG") return petalPath2
else if (d.Rated === "PG-13") return petalPath3
return petalPath4
}
Insert cell
function petPathFunc(x) {
if (x === "G") return petalPath
else if (x === "PG") return petalPath2
else if (x === "PG-13") return petalPath3
return petalPath4
}
Insert cell
// index.html you'd just create an svg element
// here we will create a const

{
const svg = DOM.svg(petalSize * 2, petalSize * 2);

// extract single object from array
const d = data[92];
const numPetals = numPetalScale(+d.imdbVotes.replace(/\,/g, ''))
const sizePetals = sizeScale(+d.imdbRating)
const petPath = petPathFunc(d.Rated)
console.log(petPath)
const flower = {
sizePetals,
petals: _.times(numPetals, i => {
return {
angle: 360 * i / numPetals,
petPath
}
}),
};
const flowers = d3.select(svg)
.selectAll('g')
.data([flower])
.enter()
.append('g')
.attr('transform', d => `translate(${petalSize}, ${petalSize})scale(${d.sizePetals})`)
flowers.selectAll('path')
.data(d => d.petals)
.enter()
.append('path')
.attr('d', d => d.petPath)
.attr('transform', d => `rotate(${d.angle})`)

return svg;

}
Insert cell
md `## Now all the flowers!`
Insert cell
{
const svg = DOM.svg(petalSize * 25, petalSize * 11)

d3.select(svg)
.append('rect')
.attr('height', "100%")
.attr('width', "100%")
.attr('fill', "#191919")
const flowers = d3.select(svg)
.selectAll('g')
.data(flowersData)
.enter()
.append('g')
// it seems like 1 % 17 determines the number of flowers per row
.attr('transform', (d, i) => `translate(${(i % 15) * petalSize + 120 },${Math.floor(i / 15) * petalSize + 70})scale(${d.sizePetals})`)
flowers.selectAll('path')
.data(d => d.petals)
.enter()
.append('path')
.attr('d', d => d.petPath)
.attr('transform', d => `rotate(${d.angle})`)
// make the color the movie rating
.attr('stroke', d => colorScale(d.genre))
.attr('fill', 'none')
.attr('stroke-width', '4')

return svg;

}
Insert cell
md `## Utility functions`
Insert cell
ratingMinMax = d3.extent(data, d => +d.imdbRating);
Insert cell
votesMinMax = d3.extent(data, d => +d.imdbVotes.replace(/[^\d\.\-]/g, ""))
Insert cell
sizeScale = d3.scaleLinear().domain(ratingMinMax).range([0.1, 0.5]);
Insert cell
numPetalScale = d3.scaleQuantize().domain(votesMinMax).range([5,7,11,15,19,20]);
Insert cell
flowersData = _.map(data, d => {
const numPetals = numPetalScale(+d.imdbVotes.replace(/\,/g, ''))
const sizePetals = sizeScale(+d.imdbRating)
const petPath = petPathFunc(d.Rated)
return {
sizePetals,
petals: _.times(numPetals, i => {
return {
angle: 360 * i / numPetals,
petPath,
rating: d.Rated,
genre: d.Genre
}
}),
}
})
Insert cell
colorScale = d3.scaleOrdinal()
.domain(d3.extent(flowersData, d => d.rating))
.range(["#CBC2DD", "#A393C0", "#4E2A84", "white"]);
Insert cell
md `## Libraries`
Insert cell
d3 = require('d3')
Insert cell
_ = require('lodash')
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