Public
Edited
Mar 25, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
canvas = {
url;
const img = new Image();
img.src = urls[url];
img.crossOrigin = "anonymous";

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

canvas.onclick = (e) => {
console.log(e, e.target, e.offsetX, e.offsetY);
Object.assign(ctx.ctxParam, { centerX: e.offsetX, centerY: e.offsetY });

const { ctxWidth, ctxHeight } = ctx.ctxParam;
ctx.drawImage(img, 0, 0, ctxWidth, ctxHeight);
drawCurve(ctx);
};

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

ctx.ctxParam = computeCtxParams(img);
// ctx.ctxImage = img;
const { ctxWidth, ctxHeight } = ctx.ctxParam;

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

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

return canvas;
}
Insert cell
/**
* Update the drawParamsBuffer
*/
{
kernelRatio;
rotateAngle;
lineWidth;
curveColor;
Object.assign(drawParamsBuffer, { kernelRatio, rotateAngle, lineWidth, curveColor });
return drawParamsBuffer;
}
Insert cell
/**
* Init drawParamsBuffer
*/
drawParamsBuffer = {
return {
kernelRatio: 0.1,
rotateAngle: 45,
lineWidth: 1,
curveColor: '#ffffff'
};
}
Insert cell
/**
* Call back for drawing curves
*/
{
url;
rotateAngle;
kernelRatio;
lineWidth;
curveColor;
Object.assign(drawParamsBuffer, {
kernelRatio,
rotateAngle,
lineWidth,
curveColor
});
const ctx = canvas.getContext("2d");

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

var k, accumulateK, thresholdK;

ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((drawParamsBuffer.rotateAngle * Math.PI) / 180);

accumulateK = 0;
k = drawParamsBuffer.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.lineWidth = 1;
ctx.strokeStyle = drawParamsBuffer.curveColor;
ctx.stroke();

ctx.beginPath();
const offset = (Math.PI / 2) * 3;
ctx.arc(0, k, k, offset, offset + Math.PI / 2);
ctx.lineWidth = drawParamsBuffer.lineWidth;
ctx.strokeStyle = drawParamsBuffer.curveColor;
ctx.stroke();

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

ctx.restore();
}
Insert cell
computeCtxParams = (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, centerX: ctxWidth / 2, centerY: ctxHeight / 2 };
}
Insert cell
img = {
url;
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",
desk: "https://images.unsplash.com/photo-1679521878363-6987b06a30f7?ixlib=rb4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
monaLisa:
"https://gist.githubusercontent.com/mbostock/9511ae067889eefa5537eedcbbf87dab/raw/944b6e5fe8dd535d6381b93d88bf4a854dac53d4/mona-lisa.jpg",
randomCityNight: "https://source.unsplash.com/random/?city,night",
randomPeople: "https://source.unsplash.com/random/?people"
};

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

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