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, this.p1.x - this.p0.x)
			);
		}
	};
	// Constraints
	Human.Constraint = class {
		constructor(p0, p1, constraint) {
			this.p0 = p0;
			this.p1 = p1;
			this.distance = p0.dist(p1);
			this.force = constraint.force || 1.0;
		}
		update() {
			this.p0.join(this.p1, this.distance, this.force);
		}
	};
	// Angles constraints
	Human.Angle = class {
		constructor(p0, p1, p2, constraint) {
			this.p0 = p0;
			this.p1 = p1;
			this.p2 = p2;
			this.len1 = p0.dist(p1);
			this.len2 = p1.dist(p2);
			this.angle = constraint.angle;
			this.range = constraint.range;
			this.force = constraint.force || 0.1;
			let m = p0.m + p1.m;
			this.m1 = p0.m / m;
			this.m2 = p1.m / m;
			m = p1.m + p2.m;
			this.m3 = p1.m / m;
			this.m4 = p2.m / m;
		}
		a12(p0, p1, p2) {
			const a = Math.atan2(p1.y - p0.y, p1.x - p0.x);
			const b = Math.atan2(p2.y - p1.y, p2.x - p1.x);
			const c = this.angle - (b - a);
			const d = c > Math.PI ? c - 2 * Math.PI : c < -Math.PI ? c + 2 * Math.PI : c;
			const e = Math.abs(d) > this.range
				? (-Math.sign(d) * this.range + d) * this.force
				: 0;
			const cos = Math.cos(a - e);
			const sin = Math.sin(a - e);
			const x1 = p0.x + (p1.x - p0.x) * this.m2;
			const y1 = p0.y + (p1.y - p0.y) * this.m2;
			p0.x = x1 - cos * this.len1 * this.m2;
			p0.y = y1 - sin * this.len1 * this.m2;
			p1.x = x1 + cos * this.len1 * this.m1;
			p1.y = y1 + sin * this.len1 * this.m1;
			return e;
		}
		a23(e, p1, p2) {
			const a = Math.atan2(p1.y - p2.y, p1.x - p2.x) + e;
			const cos = Math.cos(a);
			const sin = Math.sin(a);
			const x1 = p2.x + (p1.x - p2.x) * this.m3;
			const y1 = p2.y + (p1.y - p2.y) * this.m3;
			p2.x = x1 - cos * this.len2 * this.m3;
			p2.y = y1 - sin * this.len2 * this.m3;
			p1.x = x1 + cos * this.len2 * this.m4;
			p1.y = y1 + sin * this.len2 * this.m4;
		}
		update() {
			// resolve angular constraints
			const e = this.a12(this.p0, this.p1, this.p2);
			this.a23(e, this.p1, this.p2);
		}
	};
	const canvas = {
		// @greggman thanks for webglfundamentals!
		// https://webglfundamentals.org/webgl/lessons/webgl-2d-drawimage.html
		init() {
			// create webGL canvas context
			this.elem = document.createElement("canvas");
			document.body.appendChild(this.elem);
			const options = {
				alpha: false,
				stencil: false,
				antialias: false,
				depth: false
			};
			let gl = this.elem.getContext("webgl", options);
			if (!gl) gl = this.elem.getContext("experimental-webgl", options);
			if (!gl) return false;
			this.gl = gl;
			// set shaders
			this.vertexShader = gl.createShader(gl.VERTEX_SHADER);
			gl.shaderSource(
				this.vertexShader,
				`
				precision highp float;
        attribute vec2 aPosition;
        uniform mat3 uMatrix;
        varying vec2 vTexcoord;
        void main() {
					gl_Position = vec4(uMatrix * vec3(aPosition, 1), 1);
					vTexcoord = aPosition;
        }
      `
			);
			gl.compileShader(this.vertexShader);
			this.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
			gl.shaderSource(
				this.fragmentShader,
				`
        precision highp float;
        varying vec2 vTexcoord;
        uniform sampler2D texture;
        void main() {
           gl_FragColor = texture2D(texture, vTexcoord);
        }
      `
			);
			// compile shaders
			gl.compileShader(this.fragmentShader);
			this.program = gl.createProgram();
			gl.attachShader(this.program, this.vertexShader);
			gl.attachShader(this.program, this.fragmentShader);
			gl.linkProgram(this.program);
			// init attributes, uniforms and buffers
			this.position = gl.getAttr.........完整代码请登录后点击上方下载按钮下载查看

网友评论0