html盒子移动动画代码,HTML5/Canvas 盒子追踪动画

这篇博客展示了如何使用JavaScript、Babel和CoffeeScript创建一个动态的弹性结构。作者通过定义`World`类,设置了画布、鼠标移动事件监听器以及点和连接线的更新逻辑,实现了当鼠标靠近结构时点的位置会跟随移动。文章通过详细的代码解释了如何处理点的运动、碰撞检测和弹性效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

class World {

constructor () {

this.canvas = document.getElementById("canvas");

this.ctx = canvas.getContext("2d");

this.h = this.canvas.height = window.innerHeight;

this.w = this.canvas.width = window.innerWidth;

this.ctx.lineWidth = 2;

this.bounce = 0.1;

this.gravity = 0.1;

this.friction = 0.99;

this.points = [];

this.points.push({

x: 100,

y: 100,

oldx: 95,

oldy: 105

});

this.points.push({

x: 100,

y: 200,

oldx: 95,

oldy: 201

});

this.points.push({

x: 200,

y: 100,

oldx: 201,

oldy: 101

});

this.points.push({

x: 200,

y: 200,

oldx: 201,

oldy: 201

});

this.sticks = [];

// Square

this.connectPoints(0, 1);

this.connectPoints(1, 2);

this.connectPoints(2, 3);

this.connectPoints(3, 0);

// Support cross, diagonals

// Try commenting them out

// and see what happens! ;)

this.connectPoints(0, 2);

this.connectPoints(1, 3);

this.onMove = this.onMove.bind(this);

this.canvas.addEventListener("mousemove", this.onMove);

this.canvas.addEventListener("touchmove", this.onMove);

}

connectPoints(index0, index1) {

this.sticks.push({

p0: this.points[index0],

p1: this.points[index1],

length: this.distance(

this.points[index0],

this.points[index1]),

});

}

onMove(e) {

var x = e.touches ? e.touches[0].clientX : e.clientX;

var y = e.touches ? e.touches[0].clientY : e.clientY;

var p0 = { x: x, y: y };

var p1 = this.getClosestPoint(p0);

var dist = this.distance(p0, p1);

if(dist < 55) {

p1.oldx = x;

p1.oldy = y;

}

}

getClosestPoint(p0) {

var index = 0;

this.points.map(p1 => this.distance(p0, p1)).reduce((prev, curr, i) => {

if(curr < prev) {

index = i;

}

return Math.min(curr, prev);

});

return this.points[index];

}

distance(p0, p1) {

var x = p1.x - p0.x;

var y = p1.y - p0.y;

return Math.sqrt(x*x + y*y);

}

update() {

this.ctx.clearRect(0, 0, this.w, this.h);

this.updatePoints();

this.updateSticks();

this.drawSticks();

}

drawSticks() {

this.ctx.beginPath();

this.sticks.forEach(s => {

this.ctx.moveTo(s.p0.x, s.p0.y);

this.ctx.lineTo(s.p1.x, s.p1.y);

});

this.ctx.stroke();

}

updatePoints() {

this.points.forEach(p => {

if(!p.pinned) {

var vx = (p.x - p.oldx) * this.friction;

var vy = (p.y - p.oldy) * this.friction;

p.oldx = p.x;

p.oldy = p.y;

// Ground friction

if(p.y > this.h - this.ctx.lineWidth) {

vx *= 0.5;

}

p.x += vx;

p.y += vy;

p.y += this.gravity;

if(p.x > this.w) {

p.x = this.w;

p.oldx = p.x + vx * this.bounce;

}

if(p.x < 0) {

p.x = 0;

p.oldx = vx * this.bounce;

}

if(p.y > this.h - this.ctx.lineWidth) {

p.y = this.h - this.ctx.lineWidth;

p.oldy = p.y + vy * this.bounce;

}

if(p.y < 0) {

p.y = 0;

p.oldy = vy * this.bounce;

}

}

});

}

updateSticks() {

this.sticks.forEach(s => {

var dx = s.p1.x - s.p0.x;

var dy = s.p1.y - s.p0.y;

var dist = Math.sqrt(dx*dx + dy*dy);

var diff = s.length - dist;

var percent = diff / dist / 2;

var offsetX = dx * percent;

var offsetY = dy * percent;

s.p0.x -= offsetX;

s.p0.y -= offsetY;

s.p1.x += offsetX;

s.p1.y += offsetY;

});

}

}

var world = new World();

function animate() {

world.update();

requestAnimationFrame(animate);

}

animate();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值