Published
Edited
Oct 14, 2019
1 fork
7 stars
Insert cell
Insert cell
Insert cell
image
Insert cell
viewof simplifyThreshold = html`<input type="number" min=1 max=250 value=25 />`
Insert cell
outlinePolyline = new Promise(function(resolve, reject) {
if (!image) {
reject('Waiting for image...');
}
getImageOutline(image.src, { simplifyThreshold }, function(err, outline) {
if (err) {
reject(err);
return;
}
resolve(outline);
});
})
Insert cell
outlinePathData = 'M ' +
outlinePolyline.map(p => p.x + ' ' + p.y).join(' L ') +
' Z '
Insert cell
outlinePreview = html`
<svg width="${image.width}" height="${image.height}">
<path d="${outlinePathData}" stroke="black" fill="none" />
</svg>
`
Insert cell
colors = ['#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303']
Insert cell
expandWidth = 12
Insert cell
Insert cell
forrestoPathExpandArt = {
const { width, height } = image;
const paths = [];
mutable percentDone = 0;
yield html`
<svg width="${width}" height="${height}">
<rect fill="black" x="0" y="0" width="${width}" height="${height}" />
<g id="paths"></g>
<image href="${image.src}" x="0" y="0" width="${width}" height="${height}" />
</svg>`;
await Promises.tick(1000);

for (const path of pathExpansions(makerModel, colors)) {
paths.push(path);
mutable percentDone = Math.round((paths.length / colors.length) * 100);
yield html`
<svg width="${width}" height="${height}">
<defs>
<filter id="shadow">
<feDropShadow dx="0" dy="1" stdDeviation="2" flood-color="black" flood-opacity="0.3"/>
</filter>
</defs>
<rect fill="black" x="0" y="0" width="${width}" height="${height}" />
<g id="paths">
${paths}
</g>
<image href="${image.src}" x="0" y="0" width="${width}" height="${height}" />
</svg>`;
await Promises.tick(1000);
}
}
Insert cell
function* pathExpansions(makerModel, colors) {
for (let i = 0, len = colors.length; i < len; i++) {
const color = colors[i];
const expandBy = (len - i) * expandWidth + 0.0001;
const d = expandPath(makerModel, expandBy);
yield svg`<path stroke="none" fill="${color}" d="${d}" style="filter:url(#shadow)" />`;
}
}
Insert cell
makerModel = {
const m = makerjs.model.mirror(
new makerjs.models.ConnectTheDots(
true, // is closed
outlinePolyline.map(point => [point.x, point.y])
),
false, // Don't flip x
true // Flip y
);
// makerjs.model.originate(m);
makerjs.model.simplify(m);
return m;
}
Insert cell
expandPath = (makerModel, expandBy = 2) => {
// IDK why we need + 0.001 here
const expanded = makerjs.model.outline(makerModel, expandBy);
// makerjs.model.simplify(expanded);
const svg = html`${makerjs.exporter.toSVG(expanded, {
// viewbox: false,
origin: [0, 0]
})}`;
return svg.querySelector('path').getAttribute('d');
}
Insert cell
Insert cell
Insert cell
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