Published
Edited
Aug 17, 2020
Importers
Insert cell
Insert cell
Insert cell
import {slide} from "@mbostock/slide"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
topGenres = ["Action", "Comedy", "Animation", "Drama"]
Insert cell
petalColors = ['#bbadff', '#cbf2bd', '#afe9ff', '#ffb09e']
Insert cell
colorObj = {
const colors = _.zipObject(topGenres, petalColors)
colors.Other = '#FFF2B4'
return colors
}
Insert cell
rated = ['G', 'PG', 'PG-13', 'R']
Insert cell
petalPaths = [
petalPathFire,
petalMidVeinPath,
window.localStorage.petalPath || petalPathTulip,
pathPetalBackup1
]
Insert cell
pathPetalBackup1 = 'M0,0 C50,40 50,70 20,100 L0,85 L-20,100 C-50,70 -50,40 0,0'
Insert cell
petalPathBackup2 = 'M-35,0 C-25,25 25,25 35,0 C50,25 25,75 0,100 C-25,75 -50,25 -35,0'
Insert cell
petalPathFire = 'M0,85 L-20,100 C-55,70, -40,50, -30,40 L-20,60 C-35,20 -10,25 0,0 M0,85 L20,100 C55,70 40,50 30,40 L20,60 C35,20 10,25 0,0'
Insert cell
petalMidVeinPath = 'M0,0 C-10,45 -35,65 0,100 M0,0 C20,15 40,55 0,100 M0,100 C-5,80 15,30 0,0 C15,30 -5,80 0,100'
Insert cell
petalPathTulip = 'M0,0 C-1,15 -15,30 -10,60 C-10,65 -20,10 -25,10 C-16,30 -65,95 -15,100 C-15,100 0,75 15,100 C65,95 16,30 25,10 C25,10 20,10 10,60 C15,30 1,15 0,0'
Insert cell
localStorage.setItem('petalPath', petalPathTulip)
Insert cell
console.log(localStorage.getItem('petalPath'))
Insert cell
pathObj = _.zipObject(rated, petalPaths)
Insert cell
pathColors = ['#46e276', '#6e94e7', '#b877e9', '#f25d75']
Insert cell
Insert cell
scrollSVG = (svg) => {
return html`<div style='max-height:${width/2}px;overflow-y:scroll;overflow-x:hidden;'>${svg}</div>`
}
Insert cell
pathWidth = 120
Insert cell
perRow = Math.floor(width / pathWidth)
Insert cell
svgHeight = (Math.ceil(movies.length / perRow) + 0.5) * pathWidth
Insert cell
calculateGridPos = (i) => {
return [(i % perRow + 0.5) * pathWidth, (Math.floor(i / perRow) + 0.5) * pathWidth]
}
Insert cell
transformCode = (positions, transform1, transform2) => {
return html`
<code style='font-size: 2.3vw; font-weight: bold;'>
&lt;rect x=${positions.x} y=${positions.y} />
</code>

<pre><code style='font-size: 2.3vw; color: ${pathColors[1]}; font-weight: bold;'>&lt;rect x=${positions.x} y=${positions.y}
transform='${transform1}' /></code></pre>

${transform2 ?
`<pre><code style='font-size: 2.3vw; color: ${pathColors[2]}; font-weight: bold;'>&lt;rect x=${positions.x} y=${positions.y}
transform='${transform2}' /></code></pre>`
: ''
}
`
}
Insert cell
transformSVG = (positions, transform1, transform2) => {
const margin = {left: 30, top: 15}
const el = html`
<svg width=${textWidth + margin.left} height=${textWidth / 2 + margin.top}>
<g transform='translate(${margin.left}, ${margin.top})'>
<g>
<rect width=100 height=100 x=${positions.x} y=${positions.y} />
<g class='x axis' />
<g class='y axis' />
</g>
<g id='transform1' opacity=0.75 transform='${transform1}'>
<rect width=100 height=100 x=${positions.x} y=${positions.y} fill=${pathColors[1]} />
<g class='x axis' />
<g class='y axis' />
</g>

${transform2 ?
`<g id='transform2' opacity=0.75 transform='${transform2}'>
<rect width=100 height=100 x=${positions.x} y=${positions.y} fill=${pathColors[2]} />
<g class='x axis' />
<g class='y axis' />
</g>` : ''
}
</g>
</svg>
`
// helpers
const xAxis = d3.axisTop()
.scale(d3.scaleLinear().domain([0, textWidth]).range([0, textWidth]))
.tickSizeInner(-textWidth / 2)
.tickSizeOuter(0)
.ticks(4)
const yAxis = d3.axisLeft()
.scale(d3.scaleLinear().domain([0, textWidth / 2]).range([0, textWidth / 2]))
.tickSizeInner(-textWidth)
.tickSizeOuter(0)
.ticks(4)

// rendering
const svg = d3.select(el)
svg.selectAll('.x.axis').call(xAxis)
svg.selectAll('.y.axis').call(yAxis)
svg.selectAll('.axis').selectAll('line')
.attr('stroke-dasharray', '5 2')
.attr('opacity', 0.5)
svg.selectAll('.axis').selectAll('text')
.style('font-size', '1.2em')
// translated elements
svg.select('#transform1').selectAll('line, path')
.attr('stroke', pathColors[1]).attr('stroke-width', 2)
svg.select('#transform1').selectAll('text')
.attr('fill', pathColors[1])
.style('font-weight', 'bold')
if (transform2) {
svg.select('#transform2').selectAll('line, path')
.attr('stroke', pathColors[2]).attr('stroke-width', 2)
svg.select('#transform2').selectAll('text')
.attr('fill', pathColors[2])
.style('font-weight', 'bold')
}
return el
}
Insert cell
textWidth = 640
Insert cell
md`
## Appendix
`
Insert cell
movies = FileAttachment("movies (1).json").json()
.then(data => {
return _.chain(data)
.map(d => {
return {
title: d.Title,
released: new Date(d.Released),
genres: d.Genre.split(', '),
rating: +d.imdbRating,
votes: +(d.imdbVotes.replace(/,/g, '')),
rated: d.Rated,
}
}).sortBy(d => -d.released).value()
})
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