Public
Edited
Mar 24, 2023
Insert cell
Insert cell
viewof url = Inputs.select(urls.names, { label: "Image url" })
Insert cell
viewof curveColor = Inputs.color({ label: "Curve color", value: "#4682b4" })
Insert cell
Insert cell
Insert cell
{
kernelRatio;
rotateAngle;
Object.assign(drawParams, { kernelRatio, rotateAngle });
}
Insert cell
drawParams = {
return {
kernelRatio: 0.1,
rotateAngle: 45
};
}
Insert cell
canvas = {
url;
const img1 = new Image();
img1.src = urls[url];
img1.crossOrigin = "anonymous";

const canvas = DOM.canvas(),
ctx = canvas.getContext("2d");

canvas.onclick = (e) => {
console.log(e, e.target, e.offsetX, e.offsetY);
Object.assign(curveCoordinate, { x: e.offsetX, y: e.offsetY });

const ctx = canvas.getContext("2d");
const { ctxWidth, ctxHeight } = curveCoordinate;
ctx.drawImage(img1, 0, 0, ctxWidth, ctxHeight);
drawCurve(ctx);
};

img1.onload = function () {
const { width: imgWidth, height: imgHeight } = img;

const { ctxWidth, ctxHeight } = fitCtxSize(img);

Object.assign(canvas, { width: ctxWidth, height: ctxHeight });

ctx.drawImage(img, 0, 0, ctxWidth, ctxHeight);
drawCurve(ctx);
};

return canvas;
}
Insert cell
/**
* Call back for drawing curves
*/
{
url;
rotateAngle;
kernelRatio;
const ctx = canvas.getContext("2d");
const { ctxWidth, ctxHeight } = curveCoordinate;

ctx.drawImage(img, 0, 0, ctxWidth, ctxHeight);
drawCurve(ctx);
}
Insert cell
function drawCurve(ctx) {
console.log("Draw curve");
const { ctxWidth: width, ctxHeight: height } = curveCoordinate,
R = width > height ? width : height,
scale = d3.scaleLinear().domain([0, 1]).range([0, R]);

var k, accumulateK, thresholdK;

ctx.save();
ctx.translate(curveCoordinate.x, curveCoordinate.y);
ctx.rotate((drawParams.rotateAngle * Math.PI) / 180);

accumulateK = 0;
k = drawParams.kernelRatio * R;
thresholdK = R * 10;

for (let i = 0; i < R; ++i) {
accumulateK += k;
if (accumulateK > thresholdK) break;

ctx.beginPath();
ctx.rect(0, 0, k, k);
ctx.strokeStyle = curveColor;
ctx.stroke();

ctx.translate(k, k);
ctx.rotate(Math.PI / 2);
k *= gInv;
}

ctx.restore();
}
Insert cell
curveCoordinate = {
const { ctxWidth, ctxHeight } = fitCtxSize(img);
return { x: ctxWidth / 2, y: ctxHeight / 2, ctxWidth, ctxHeight };
}
Insert cell
fitCtxSize = (img) => {
const width = 600;

const { width: imgWidth, height: imgHeight } = img;

var ctxWidth, ctxHeight;

if (imgWidth > imgHeight) {
ctxWidth = width;
ctxHeight = (width / imgWidth) * imgHeight;
} else {
ctxHeight = width;
ctxWidth = (width / imgHeight) * imgWidth;
}

return { ctxWidth, ctxHeight };
}
Insert cell
img = {
const img = new Image();
img.src = urls[url];
// img.crossOrigin = "anonymous";
return img;
}
Insert cell
gInv = 1 / g
Insert cell
g = (Math.sqrt(5) - 1) / 2
Insert cell
canvas.getContext("2d").getImageData(0, 0, 100, 100)
Insert cell
urls = {
const urls = {
sunset:
"https://images.unsplash.com/photo-1679421138674-aec9e1c319a8?ixlib=rb4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
montain:
"https://images.unsplash.com/photo-1679572255334-08dd1c8cbdd7?ixlib=rb4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1345&q=80",
monaLisa:
"https://gist.githubusercontent.com/mbostock/9511ae067889eefa5537eedcbbf87dab/raw/944b6e5fe8dd535d6381b93d88bf4a854dac53d4/mona-lisa.jpg"
};

const names = [];
for (let name in urls) {
names.push(name);
}
Object.assign(urls, { names });

return urls;
}
Insert cell
d3 = require("d3")
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