Skip to content

Instantly share code, notes, and snippets.

@mmpataki
Created August 5, 2025 19:59
Show Gist options
  • Select an option

  • Save mmpataki/bba644d9ace0caab03fb6de7db772e42 to your computer and use it in GitHub Desktop.

Select an option

Save mmpataki/bba644d9ace0caab03fb6de7db772e42 to your computer and use it in GitHub Desktop.
movable ladybug
function MoveableItem(img, initX, initY) {
/* non class functions */
function now() { return +(new Date()) }
function move(img, x, y) {
img.style.left = `${x}px`
img.style.bottom = `${y}px`
}
function rotate(img, deg) {
img.style.transform = `rotate(${deg}deg)`
}
function decideMoveParams(curX, curY, newX, newY) {
console.debug(curX, curY, newX, newY)
// find the distance
let dist = Math.sqrt(Math.pow(newX - curX, 2) + Math.pow(newY - curY, 2))
// move these many pixels per frame
let pxPerFrame = 5;
// these many steps
let steps = dist / pxPerFrame;
// delta X move per step
let dx = (newX - curX) / steps;
let dy = (newY - curY) / steps;
// find the angle too
let theta = Math.atan2((newY - curY), (newX - curX)) * (180 / Math.PI)
console.debug(steps, dx, dy, theta)
return { steps, dx, dy, theta }
}
/* class functions */
this.mouseMoved = () => {
this.lastMove = now();
if (this.moving) {
clearInterval(this.moving);
this.moving = undefined;
this.setupMotionChecker()
move(this.img, this.initX, this.initY)
}
}
this.move_look_repeat = () => {
let moveState = this.moveState;
if (moveState.steps <= 0) {
let bcr = document.body.getBoundingClientRect();
let MX = bcr.width, MY = bcr.height;
//let MX = 400, MY = 400;
this.moveState = moveState = { ...moveState, ...decideMoveParams(moveState.curX, moveState.curY, Math.random() * MX, Math.random() * MY) }
rotate(this.img, 90 - moveState.theta);
}
//console.log(JSON.stringify(moveState))
move(this.img, moveState.curX += moveState.dx, moveState.curY += moveState.dy);
moveState.steps--;
}
// image to move
this.img = img;
this.initX = initX;
this.initY = initY;
// state of the movement
this.moveState = { curX: initX, curY: initY, steps: 0, dx: 0, dy: 0, theta: 90 };
// when did mouse move last?
this.lastMove = now();
// move schedule
this.moving = undefined;
this.motionChecker = undefined;
this.scheduleMove = () => {
this.moving = setInterval(_ => this.move_look_repeat(), 50);
}
this.checkMotion = () => {
if (now() - this.lastMove > 5000) {
clearInterval(this.motionChecker);
this.scheduleMove();
}
}
this.setupMotionChecker = () => {
this.motionChecker = setInterval(_ => this.checkMotion(), 5000);
}
window.addEventListener('mousemove', _ => this.mouseMoved())
this.setupMotionChecker()
}
let btn = document.createElement('button')
btn.innerText = 'hello'
new MoveableItem(btn, 15, 15)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment