canvas实现鼠标悬浮拖动铅球重力感应效果代码

代码语言:html

所属分类:动画

代码描述:canvas实现鼠标悬浮拖动铅球重力感应效果代码

代码标签: canvas 鼠标 悬浮 拖动 铅球 重力 感应 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
<style>
    body, html {
	position: absolute;
	margin: 0;
	padding: 0;
	width: 100%;
	height: 100%;
	overflow: hidden;
}

canvas {
	position: absolute;
	width: 100%;
	height: 100%;
	cursor: none;
}
</style>

</head>
<body>

  <script >
      {
	// Code never lies, comments sometimes do.
	const Human = class {
		constructor(size, gravity, x, y, struct) {
			this.x = x;
			this.y = y;
			this.points = [];
			this.constraints = [];
			this.angles = [];
			this.shapes = [];
			// Points
			for (const point of struct.points) {
				this.points.push(
					new Human.Point(canvas.width * x, canvas.height * y, point, size, gravity)
				);
			}
			// constraints and shapes
			for (const constraint of struct.constraints) {
				const p0 = this.points[constraint.p0];
				const p1 = this.points[constraint.p1];
				this.constraints.push(new Human.Constraint(p0, p1, constraint));
				if (constraint.svg) {
					this.shapes.push(
						new Human.Shape(p0, p1, constraint, struct.svg[constraint.svg], size)
					);
				}
			}
			// angle constraints
			for (const angle of struct.angles) {
				this.angles.push(
					new Human.Angle(
						this.points[angle.p0],
						this.points[angle.p1],
						this.points[angle.p2],
						angle
					)
				);
			}
		}
		anim() {
			for (const point of this.points) point.integrate();
			for (let i = 0; i < 5; ++i) {
				for (const angle of this.angles) angle.update();
				for (const constraint of this.constraints) constraint.update();
			}
			
			for (const point of this.points) point.collide(ball);
		}
		draw() {
			for (const shape of this.shapes) shape.draw();
		}
	};
	// Points
	Human.Point = class {
		constructor(x, y, p, s, g) {
			this.x = x + p.x * s;
			this.y = y + p.y * s;
			this.px = this.x;
			this.py = this.y;
			this.vx = 0.0;
			this.vy = 0.0;
			this.m = p.m || 1.0;
			this.g = g;
		}
		join(p1, distance, force) {
			const dx = p1.x - this.x;
			const dy = p1.y - this.y;
			const dist = Math.sqrt(dx * dx + dy * dy);
			const tw = this.m + p1.m;
			const r1 = p1.m / tw;
			const r0 = this.m / tw;
			const dz = (distance - dist) * force;
			const sx = dx / dist * dz;
			const sy = dy / dist * dz;
			p1.x += sx * r0;
			p1.y += sy * r0;
			this.x -= sx * r1;
			this.y -= sy * r1;
		}
		dist(p1) {
			const dx = this.x - p1.x;
			const dy = this.y - p1.y;
			return Math.sqrt(dx * dx + dy * dy);
		}
		integrate() {
			// verlet integration
			this.vx = this.x - this.px;
			this.vy = this.y - this.py;
			this.px = this.x;
			this.py = this.y;
			this.x += this.vx;
			this.y += this.vy + this.g;
		}
		collide(ball) {
			// collision with ball
			const dx = this.x - ball.x;
			const dy = this.y - ball.y;
			const sd = dx * dx + dy * dy;
			if (sd < ball.radius * ball.radius) {
				const d = Math.sqrt(sd);
				const dz = (ball.radius - d) * 0.5;
				this.x += dx / d * dz;
				this.y += dy / d * dz;
			}
		}
	};
	// Shapes
	Human.Shape = class {
		constructor(p0, p1, shape, src, size) {
			this.p0 = p0;
			this.p1 = p1;
			this.width = shape.w * size;
			this.height = shape.h * size;
			this.shape = canvas.createImage(
				shape.svg,
				"data:image/svg+xml;base64," + window.btoa(src)
			);
			this.offset = shape.offset;
		}
		draw() {
			canvas.drawImage(
				this.shape,
				this.p0.x,
				this.p0.y,
				this.height + this.width * this.offset,
				this.width,
				-this.height * this.offset,
				-this.width * 0.5,
				Math.atan2(this.p1.y - this.p0.y.........完整代码请登录后点击上方下载按钮下载查看

网友评论0