Published
Edited
Jun 14, 2022
9 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {blogSubscribeFooter} from "615860c65e5663a6"
Insert cell
import {convolveY2, Kx, Ky} with {avatarSize as width, avatarSize as height} from "@mbostock/sobel-operator"
Insert cell
avatarSize = Math.floor((Math.min(640, width) - (16 * 3)) / 8) * 2
Insert cell
function genAvatar({size = 64} = {}) {
const c = document.createElement("canvas");
c.width = size;
c.height = size;
const ctx = c.getContext("2d");

const h1 = Math.floor(Math.random() * 360);
const hDelta = Math.random() * 40 + 20;
const h2 = h1 > 300 ? h1 - hDelta : h1 + hDelta;
const s = Math.floor(Math.random() * 40) + 40;
const l1 = Math.floor(Math.random() * 30) + 30;
const l2 = Math.floor(Math.random() * 30) + 50;

const r = size / 2;
const ang = Math.random() * Math.PI * 2;
const cx = (Math.cos(ang) + 1) * r;
const cy = (Math.sin(ang) + 1) * r;
const gradCenter = [cx, cy, size * 0.1];
const gradEdge = [cx, cy, size * 1.1];

const gradient = ctx.createRadialGradient(...gradCenter, ...gradEdge);
gradient.addColorStop(0, `hsl(${h1}, ${s}%, ${l1}%`);
gradient.addColorStop(1, `hsl(${h2}, ${s}%, ${l2}%`);

ctx.fillStyle = gradient;
ctx.fillRect(0, 0, size, size);

return c;
}
Insert cell
demoAvatarUrls = [
{title: "Cartoon avatar", url: await FileAttachment("demo-avatar-1.jpg").url()},
{title: htl.html`<a href="https://observablehq.com/@waynsutton">@waynesutton</a>`, url: await FileAttachment("wayne-avatar.jpg").url()},
{title: "Generated avatar", url: await genAvatar({size: avatarSize}).toDataURL("image/png")},
{title: "Google avatar", url: await FileAttachment("demo-avatar-4.jpg").url()},
]
Insert cell
async function createContext(image) {
await new Promise((resolve) => {
if (image.naturalWidth) resolve();
function onLoad() { resolve() }
image.addEventListener('load', onLoad);
invalidation.then(image => removeEventListener('load', onLoad));
});
const context = DOM.context2d(avatarSize, avatarSize, 1);
context.canvas.style = "max-width: 100%;";
context.drawImage(image, 0, 0, avatarSize, avatarSize);
return context;
}
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