Public
Edited
Nov 17, 2024
Paused
Fork of Simple SVG
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
faceMove
Insert cell
Insert cell
Insert cell
faceMoveScale = 2
Insert cell
Insert cell
Insert cell
Insert cell
function drawIndexes(n, m) {
return _.range(n).map((d) => _.random(0, m));
}
Insert cell
mutable aIndexes = drawIndexes(5, qd.bush.length - 1)
Insert cell
mutable bIndexes = drawIndexes(5, qd.bush.length - 1)
Insert cell
t = {
let t = 0;
let n = 60;
let kPrev = 0;
while (true) {
t += 1;
let k = Math.PI * (t / n - 1 / 2);
if (!((t + n) % (2 * n))) {
mutable aIndexes = drawIndexes(5, qd.bush.length - 1);
}
if (!((t + 0) % (2 * n))) {
mutable bIndexes = drawIndexes(5, qd.bush.length - 1);
}
yield 0.5 + 0.5 * Math.sin(k + Math.cos(k) * Math.sin(k));
}
}
Insert cell
// returns an array of arrays: each one is an array of [x, y] coordinates that makes up one of the lines in the drawing, scaled to fit inside the given bounding box
function getShape(
names,
index,
{ xmin = 0, xmax = 1, ymin = 0, ymax = 1 } = {}
) {
const shape = _.sample(names);
const drawing = qd[shape][index];
const xScale = d3.scaleLinear().domain([0, 255]).range([xmin, xmax]);
const yScale = d3.scaleLinear().domain([0, 255]).range([ymin, ymax]);
return _.map(drawing, (coords) =>
coords.map(([x, y]) => [xScale(x), yScale(y)])
);
}
Insert cell
function makeFaceShapes(indexes) {
const names = ["leftEye", "rightEye", "nose", "mouth", "head"];
const parts = [
["eye"],
["eye"],
["nose"],
["mouth"],
["square", "circle", "hexagon", "octagon"]
];
const boxes = [leftEyeBBox, rightEyeBBox, noseBBox, mouthBBox, headBBox];
const result = {};
_.zip(names, parts, indexes, boxes).forEach(
([name, shapes, i, bbox]) => (result[name] = getShape(shapes, i, bbox))
);
return result;
}
Insert cell
aShapes = makeFaceShapes(aIndexes)
Insert cell
bShapes = makeFaceShapes(bIndexes)
Insert cell
morphers = {
const result = {};
for (let key of Object.keys(aShapes)) {
result[key] = makeMorpher(aShapes[key], bShapes[key]);
}
return result;
}
Insert cell
leftEyeBBox = ({
xmin: 1,
xmax: 2,
ymin: 2,
ymax: 3
})
Insert cell
rightEyeBBox = ({
xmin: 2.5,
xmax: 3.5,
ymin: 2,
ymax: 3
})
Insert cell
noseBBox = ({
xmin: 1.75,
xmax: 2.75,
ymin: 2.5,
ymax: 3.5
})
Insert cell
mouthBBox = ({
xmin: 1.25,
xmax: 3.25,
ymin: 3.5,
ymax: 4.5
})
Insert cell
headBBox = ({
xmin: 0,
xmax: 5,
ymin: 0,
ymax: 5
})
Insert cell
Insert cell
interp = require("d3-interpolate-path@2.3.0/build/d3-interpolate-path.js")
Insert cell
function makeMorpher(qdA, qdB) {
const line = d3.line();
const dInterpolators = _.zip(qdA, qdB).map(([a, b], i) => {
return interp.interpolatePath(line(a ? a : ""), line(b ? b : ""));
});
const dInterpolator = (t) => dInterpolators.map((f) => f(t)).join(" ");
return {
d: dInterpolator
};
}
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