Public
Edited
Sep 27, 2021
Insert cell
md`# 📑 Recursive Frames`
Insert cell
viewof n=html`<input type='number' id='n_frames' value=1
style='width:200px; font-size:120%; color:#363636;
background-color:silver; text-align:center;'>`
Insert cell
viewof m=html`<input type='number' id='m_frames' value=7
style='width:200px; font-size:120%; color:#363636;
background-color:silver; text-align:center;'>`
Insert cell
frame(n,m)
Insert cell
frame=function(n,m) {
const svg=d3.select(DOM.svg(size,size))
.attr('style','background:silver');
let adds=[1000,1600,2000,2700,3100,3900];
svg.selectAll('.curve').data(adds).join('path')
.attr('d',(_,i)=>line(recursive_curve(size,m,i+n))+'z')
.style('fill',d=>d3.interpolateSinebow((d+now)/6000))
.style('fill-opacity',(_,i)=>.01*i)
.style('stroke',d=>d3.interpolateSinebow((d+now)/6000))
.style('stroke-width',2);
return svg.node();}
Insert cell
recursive_curve=function(len,m,iterations) {
const contour1=[[0,len],[0,0],[len,0]],
contour2=[[len,0],[len,len],[0,len]]
const half1=subdivpoly(contour1,m,iterations),
half2=subdivpoly(contour2,m,iterations)
return [...half1,...half2];}
Insert cell
function subdivpoly(poly,m,iterations=1) {
const [p1,p2,p3]=poly,points=[]
const centroid=d3.polygonCentroid(poly)
if (iterations===0) {points.push(centroid)}
else {const subset1=[p1,subpoint(p1,p3,m),p2],
subset2=[p2,subpoint(p1,p3,m),p3];
points.push(...subdivpoly(subset1,m,iterations-1))
points.push(...subdivpoly(subset2,m,iterations-1))}
return points}
Insert cell
size = 580
Insert cell
line=d3.line()
Insert cell
function subpoint(a,b,m) {
return [Math.floor(m/2)*(a[0]+b[0])/m,
Math.floor(m/2)*(a[1]+b[1])/m]}
Insert cell
d3 = require("d3@6")
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