Public
Edited
Mar 19, 2024
Insert cell
Insert cell
Insert cell
petalPath = 'M 0,0 C -15,-10 -15,-40, 0,-50 C 15,-40 15,-10 0,0 '
Insert cell
petalPath2 = 'M0,0 C-26,-12 -40,-60 0,-45 C40,-60, 26,-12, 0,0'

Insert cell
petalPath2x = 'M 0,0 C -30,0 -15,40, 0,50 C 15,40 30,0 0,0'
Insert cell
<svg widht='100' height ='100'><path transform="translate(50,75)" d="${petalPath}"></path></svg>
Insert cell
petalPath3 = 'M 0,0 C -30,0 -15,-40, 0,-50 C 15,-40 30,0 0,0 '
Insert cell
Insert cell
petalPath4 = 'M 0,0 C -35,-10 0,-30, 0,-50 C 0,-30 35,-10 0,0 '
Insert cell
Insert cell
d3 = require('d3');
Insert cell
data =d3.json("https://raw.githubusercontent.com/sxywu/filmflowers/master/movies.json").then(data => _.values(data));
Insert cell
data[12].Genre.replace(" ","").replace(" ","").split(",")
Insert cell
console.log(Object.values(data[9]));
Insert cell
_= require('lodash')
Insert cell
petalSize =50
Insert cell
petalSizeMulti = 120
Insert cell
{
const svg= DOM.svg();
svg.setAttribute("viewBox","-80 -50 700 3300");
const ratingMinMax = d3.extent(data, d => +d.imdbRating); //+ stands for parse int
const votesMinMax = d3.extent(data, d => +d.imdbVotes.replace(',', '')); //numbers are notated with a , for thousands and that messes with the parse int so remove ,
// const ratedMinMax =d3.extent(data, d=> d.Rated)
const runtimeMinMax = d3.extent(data, d=> +d.Runtime.match(/(\d+)/)[0]);
const sizeScale = d3.scaleLinear().domain(ratingMinMax).range([0.25, 1]);
const numPetalScale = d3.scaleQuantize().domain(votesMinMax).range([3,6,9,12,15,18,21]);
const ratedPetal =d3.scaleOrdinal().domain(["G","PG", "PG-13", "R" ]).range([petalPath, petalPath2, petalPath3, petalPath4])
const lineScale =d3.scaleLinear().domain(runtimeMinMax).range([0.25,3])

const colorScale =d3.scaleOrdinal().domain(["Drama", "Comedy", "Adventure", "Action", "Other"]).range(['red', 'green', 'blue', 'pink', 'yellow'])


// const d = data[92]; //only when dispalying one movie

const flowersData = _.map(data, d => {
const numPetals = numPetalScale(+d.imdbVotes.replace(',',''));
const petSize = sizeScale(+d.imdbRating);
const petalType = ratedPetal(d.Rated);
const lineThickness = lineScale(+d.Runtime.match(/(\d+)/)[0]);
const genreColor = colorScale(d.Genre.replace(" ","").replace(" ","").split(","))
const label = d.Title;
const genre = d.Genre;
console.log(genreColor);
return {
petSize,
petals: _.times(numPetals, i => {return {angle: 360 * i / numPetals, petalType}}),
numPetals,
label,
genre,
lineThickness,
genreColor,
}
});

console.log(flowersData)
const flowers = d3.select(svg)
.selectAll('g')
.data(flowersData)
.enter()
.append('g')
.attr('transform', (d, i) =>
`translate(${(i % 5) * petalSizeMulti}, ${Math.floor(i / 5) * petalSizeMulti})scale(${d.petSize})`)
.attr("stroke-width",function(d) { return (d.lineThickness); })
.style("isolation", "isolate");

//use the `` on the left side of your keyboard!!! Otherwise it won't work
//${} is to access a variable

// flowers.append("circle")
// .attr('cx', 0 )
// .attr('cy', 0 )
// .attr('r','20px')
// .style('fill', d=>d.genreColor)
// .style('opacity', 0.3)
// .style("mix-blend-mode", "screen");

flowers.selectAll('path')
.data(d => d.petals).enter().append('path')
.attr('d', d => d.petalType)
.attr('transform', d=> `rotate(${d.angle})` )
.style('stroke', 'black')
// .attr("stroke-width",function(d) { return (d.lineThickness); })
// .attr('fill', (d, i) => d3.interpolateWarm (d.angle/ 360))
.attr('fill', 'none')
.attr('opacity', '0.85');

flowers.append("text")
.attr("x", 0)
.attr("y", d => Math.floor(60/d.petSize))
.attr('font-size', d => 8/ d.petSize)
.attr('text-anchor', 'middle')
.text(function(d) { return d.label; });


return svg;
}
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