Public
Edited
Nov 17
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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more