Public
Edited
Mar 3, 2022
Insert cell
Insert cell
Insert cell
{
const svgBackgroundColor = '#c2b502',
height = 400,
width = 400,

blockColor = '#b784a7',
svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", svgBackgroundColor),
container = svg.append("g")
.attr("transform", `translate(${width/2},${height/2})`),

numCols = 5,
numRows = 5,
numSquares = numCols * numRows,
squareSize = 30,
expandedSquareSize = squareSize * 2,
data = d3.range(numSquares);

//scales for the initial shape grid, and the expanded grid
let x1 = d3.scaleBand()
.domain(d3.range(numCols))
.range([-(squareSize*numCols)/2,(squareSize*numCols)/2]),
y1 = d3.scaleBand()
.domain(d3.range(numRows))
.range([(squareSize*numRows)/2, -(squareSize*numRows)/2]),
xExpanded = d3.scaleBand()
.domain(d3.range(numCols))
.range([-(width/2),(width/2)]),
yExpanded = d3.scaleBand()
.domain(d3.range(numRows))
.range([(height/2), -(height/2)]);

function update(data){
let squares = container.selectAll('path')
.data(data, d => d);
squares
.join('path')
.attr("d", d => d3.line()(getPathPoints(x1(d%numCols), y1(Math.floor(d/numRows)), squareSize)))
.attr("fill", blockColor)
.style('opacity', 1)
.transition()
.duration(2000)
.delay(1000)
.attr("d", d => d3.line()(getAlteredPathPoints(xExpanded(d%numCols) + (xExpanded.bandwidth()-expandedSquareSize)/2, yExpanded(Math.floor(d/numRows)) + (yExpanded.bandwidth() - expandedSquareSize)/2, expandedSquareSize)));
}

update(data);

function reRun(){
d3.selectAll("path").remove();
update(data);
}

d3.select("button#runAnimation").on("click", reRun);

yield svg.node();
}
Insert cell
function getPathPoints(x,y,squareSize){
return [[x,y],
[x,y+squareSize],
[x+squareSize,y+squareSize],
[x+squareSize,y],[x,y]];

}
Insert cell
Insert cell
function getAlteredPathPoints(x,y,squareSize){
let points = getPathPoints(x,y,squareSize);
let corners = [0,1,2,3];
d3.shuffle(corners);
let corner1 = points[corners[0]];
let corner2 = points[corners[1]];
let coin1 = Math.random();
let coin2 = Math.random();
if(coin1 <= .5){
if(coin2 > .5){
corner1[0] = corner1[0] - (.05 * corner1[0]);
}else{
corner2[0] = corner2[0] + (.05 * corner2[0]);
};
}else{
if(coin1 < .5){
corner1[1] = corner1[1] + (.05 * corner1[1]);
}else{
corner2[1] = corner2[1] - (.05 * corner2[1]);
}
}
return points

}
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