Last active
April 28, 2022 01:19
-
-
Save artpi/1eed7ac11eb980d9f7837041d054ef3f to your computer and use it in GitHub Desktop.
This will animate an "Explosion" whenever you complete a TODO in Roam Research, so you can be productive in style.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This will animate an "Explosion" whenever you complete a TODO in Roam Research. | |
// See https://deliber.at/roam for more Roam goodies. | |
// Put this file under {{[[roam/js]]}} block. I have a page roam/js. Under that, I have {{[[roam/js]]}} and under that the javascript block | |
document.addEventListener("click", function ( e ) { | |
const target = e.target; | |
if ( | |
target.tagName === "INPUT" && | |
target.parentElement.className === "check-container" | |
) { | |
if (target.type === "checkbox" && target.checked ) { | |
const position = target.getBoundingClientRect(); | |
setTimeout(() => { | |
explode( position.x, position.y ); | |
}, 50); | |
} | |
} | |
}); | |
// The animation code below is adapted from https://codepen.io/explosion/pen/zKEovE | |
const requestedFrames = []; | |
const explode = (x, y) => { | |
const colors = [ '#ffc000', '#ff3b3b', '#ff8400' ]; | |
const bubbles = 25; | |
let particles = []; | |
let ratio = window.devicePixelRatio; | |
let c = document.createElement('canvas'); | |
let ctx = c.getContext('2d'); | |
c.style.position = 'absolute'; | |
c.style.left = (x - 100) + 'px'; | |
c.style.top = (y - 100) + 'px'; | |
c.style.pointerEvents = 'none'; | |
c.style.width = 200 + 'px'; | |
c.style.height = 200 + 'px'; | |
c.style.zIndex = 10000; | |
c.width = 200 * ratio; | |
c.height = 200 * ratio; | |
document.body.appendChild(c); | |
for(var i = 0; i < bubbles; i++) { | |
particles.push({ | |
x: c.width / 2, | |
y: c.height / 2, | |
radius: r(20, 30), | |
color: colors[Math.floor(Math.random() * colors.length)], | |
rotation: r(0, 360, true), | |
speed: r(8, 12), | |
friction: 0.9, | |
opacity: r(0, 0.5, true), | |
yVel: 0, | |
gravity: 0.1 | |
}); | |
} | |
render(particles, ctx, c.width, c.height); | |
setTimeout(() => { | |
document.body.removeChild(c); | |
requestedFrames.forEach( frame => cancelAnimationFrame( frame ) ); | |
}, 1000); | |
} | |
const render = (particles, ctx, width, height) => { | |
requestedFrames.push( requestAnimationFrame(() => render(particles, ctx, width, height)) ); | |
ctx.clearRect(0, 0, width, height); | |
particles.forEach((p, i) => { | |
p.x += p.speed * Math.cos(p.rotation * Math.PI / 180); | |
p.y += p.speed * Math.sin(p.rotation * Math.PI / 180); | |
p.opacity -= 0.01; | |
p.speed *= p.friction; | |
p.radius *= p.friction; | |
p.yVel += p.gravity; | |
p.y += p.yVel; | |
if(p.opacity < 0 || p.radius < 0) return; | |
ctx.beginPath(); | |
ctx.globalAlpha = p.opacity; | |
ctx.fillStyle = p.color; | |
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, false); | |
ctx.fill(); | |
}); | |
return ctx; | |
} | |
const r = (a, b, c) => parseFloat((Math.random() * ((a ? a : 1) - (b ? b : 0)) + (b ? b : 0)).toFixed(c ? c : 0)); | |
Hey @artpi, how would you feel if I merged this in with the todo-trigger
extension?
@dvargas92495 , yes, please do! I find it impossible to maintain this and I bet it will be easier to keep working if part of the larger project
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it happened to me too, I had to reload the browser