Published
Edited
Oct 1, 2022
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
redrawButton;
const context = DOM.context2d(width, height);

// Background is the blur image
// Foreground is the clear image

const data = clearImage.context.getImageData(0, 0, width, height);
d3.blurImage(data, blurDense);
context.putImageData(data, 0, 0);

function draw() {
context.putImageData(data, 0, 0);
drops.map((drop) => {
const { x, y, size, speed, length } = drop;
const px = x * width,
py = y * height;

context.save();

{
context.beginPath();
for (let i = 0; i < 1; ++i) {
context.save(),
context.translate(px, py),
context.rotate(0.5),
context.rotate(Math.PI),
context.scale(1, 1.4),
context.arc(0, 0, size, 0, Math.PI * 2, true),
context.restore();
}
context.closePath();
}

{
context.clip(),
context.save(),
// context.rotate(0.2),
context.translate(px, py),
context.scale(-1, -1),
// context.rotate(Math.PI),
// context.scale(1.0, 0.6),
context.drawImage(clearImage.img, -px, -py, width, height),
context.restore();
}

context.restore();
});
}

function loop() {
// DO NOT directly use the animationToggle here,
// Because it will be snaped and keep being true forever.
if (animation2State.animation) {
requestAnimationFrame(loop);
}
updateDrops();
draw();
}

if (animation2Toggle) {
// Draw loop
loop();
} else {
// Draw once
updateDrops();
draw();
}

// updateDrops();
// draw();

return context.canvas;
}
Insert cell
{
animation2State.animation = animation2Toggle;
return animation2State;
}
Insert cell
animation2State = {
const animation = false;
return { animation };
}
Insert cell
updateDrops = () => {
drops.map((drop) => {
const { speed, shrink } = drop;

drop.y += speed;
drop.size -= shrink;

if (
drop.y > 0.9 ||
drop.y < 0.1 ||
drop.x > 0.9 ||
drop.x < 0.1 ||
drop.size < 0
) {
const { x, y, size, speed } = rndDrop();
(drop.x = x), (drop.y = y), (drop.size = size), (drop.speed = speed);
}
});
}
Insert cell
rndDrop = () => {
var x, y, size, speed, shrink;

x = d3.randomUniform(0.1, 0.9)();
y = d3.randomUniform(0.1, 0.9)();
size = d3.randomInt(10, 20)();
speed = (d3.randomUniform(1, 5)() * size) / width / 100;
shrink = d3.randomUniform(0.04, 0.1)();

return { x, y, size, speed, shrink };
}
Insert cell
drops = {
const drops = [];

for (let index = 0; index < 30; ++index) {
drops.push(rndDrop());
}

return drops;
}
Insert cell
Insert cell
{
redrawButton;
const context = DOM.context2d(width, height);

// Background is the clear image
// Foreground is the blur image

function draw() {
const img = new Image();
img.src = blurImage.context.canvas.toDataURL();
img.onload = onload;

function onload() {
context.drawImage(clearImage.img, 0, 0, width, height);

var x, y, e, s;

for (let index = 0; index < 30; ++index) {
(x = Math.round(Math.random() * width)),
(y = Math.round(Math.random() * height)),
(e = 20 + Math.round(Math.random() * 30)),
(s = Math.round(Math.random() * 30));

context.save(),
context.beginPath(),
context.arc(x, y, s, 0, Math.PI * 2, true),
context.closePath(),
context.clip(),
context.drawImage(img, 0, 0, width, height),
context.restore();
}
}
}

draw();

return context.canvas;
}
Insert cell
Insert cell
Insert cell
contextAnimation1.canvas
Insert cell
contextAnimation1 = {
animation1Toggle;
const context = DOM.context2d(width, height);
return context;
}
Insert cell
{
// Update context

const context = contextAnimation1;

const xScale = d3.scaleLinear().domain([-1, 1]).range([0, width]),
yScale = d3.scaleLinear().domain([-1, 1]).range([0, height]);

function draw() {
updatePosition();

const img = new Image();
const x = xScale(position.x),
y = yScale(position.y);
// console.log(x, y);

img.src = blurImage.context.canvas.toDataURL();
img.onload = onload;
function onload() {
context.drawImage(clearImage.img, 0, 0, width, height);

// Draw mask
context.save(),
context.beginPath(),
context.arc(x, y, 100, 0, Math.PI * 2, true),
context.closePath(),
context.clip(),
context.drawImage(img, 0, 0, width, height);

context.restore();
}
}

function loop() {
// DO NOT directly use the animationToggle here,
// Because it will be snaped and keep being true forever.
if (animation1State.animation) {
requestAnimationFrame(loop);
}
draw();
}

if (animation1Toggle) {
// Draw loop
loop();
} else {
// Draw once
draw();
}
}
Insert cell
{
animation1State.animation = animation1Toggle;
}
Insert cell
animation1State = {
const animation = false;
return { animation };
}
Insert cell
updatePosition = () => {
const t = new Date().getTime() / 1000;
position.x = Math.cos(t);
position.y = Math.sin(t);
}
Insert cell
position = {
const x = 0.5,
y = 0.5;
return { x, y };
}
Insert cell
Insert cell
clearImage.context.canvas
Insert cell
blurImage.context.canvas
Insert cell
clearImage = ((rawImg) => {
const context = DOM.context2d(width, height);

const img = new Image();
img.src =rawImg.src;
img.setAttribute('crossOrigin', '');
img.onload = () => {
context.drawImage(img, 0, 0, width, height);
};

return { context, img };
})(image1)
Insert cell
blurImage = ((rawImg) => {
const context = DOM.context2d(width, height);

const img = new Image();
img.src = rawImg.src;
img.setAttribute("crossOrigin", "");
img.onload = () => {
context.drawImage(img, 0, 0, width, height);
const data = context.getImageData(0, 0, width, height);
d3.blurImage(data, blurDense);
context.putImageData(data, 0, 0);
};

return { context, img };
})(image1)
Insert cell
Insert cell
image1 = FileAttachment("BingImageOfTheDay@3.jpg").image()
Insert cell
height = width / 2
Insert cell
// width = 800
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