canvas实现弹性绳子手掌反重力交互效果代码
代码语言:html
所属分类:动画
代码描述:canvas实现弹性绳子手掌反重力交互效果代码,试试用鼠标抓住两个手掌。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<style>
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
touch-action: none;
cursor: none;
}
</style>
</head>
<body>
<!-- partial:index.partial.html -->
<canvas id="canvas"></canvas>
<!-- partial -->
<script >
function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}
function lerp(a, b, n) {
return (1 - n) * a + n * b;
}
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Canvas
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Canvas {
constructor({ canvas, entities = [], pointer }) {_defineProperty(this, "setCanvasSize",
() => {
const { innerWidth: w, innerHeight: h } = window;
const w2 = w * this.dpr;
const h2 = h * this.dpr;
this.canvas.width = w2;
this.canvas.height = h2;
this.canvas.style.width = w + 'px';
this.canvas.style.height = h + 'px';
this.bounds = new Bounds(0, 0, w2, h2);
});_defineProperty(this, "addEntity",
newEntity => {
this.entities = [...this.entities, newEntity];
return this.entities.length - 1;
});_defineProperty(this, "render",
() => {
// Main loop
// Draw and Update items here.
this.entities.forEach(({ draw, update }) => {
draw(this);
update(this);
});
++this.tick;
window.requestAnimationFrame(this.render);
}); // setup a canvas
this.canvas = canvas;this.dpr = window.devicePixelRatio || 1;this.ctx = canvas.getContext('2d');this.ctx.scale(this.dpr, this.dpr); // tick counter
this.tick = 0; // entities to be drawn on the canvas
this.entities = entities; // track mouse/touch movement
this.pointer = pointer || null; // setup and run
this.setCanvasSize();this.setupListeners();this.render();}setupListeners() {window.addEventListener('resize', this.setCanvasSize);}removeEntity(deleteIndex) {this.entities = this.entities.filter((el, i) => i !== deleteIndex);return this.entities;}} //*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Entity
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Entity {constructor() {_defineProperty(this, "dpr", window.devicePixelRatio || 1);_defineProperty(this, "toValue",
value => value * this.dpr);_defineProperty(this, "draw",
() => {});_defineProperty(this, "update",
() => {});}}
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Background
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Background extends Entity {
constructor({ color }) {
super();_defineProperty(this, "draw",
context => {
this.drawBg(context);
});this.color = color;}drawBg({ ctx, canvas, bounds }) {ctx.fillStyle = this.color;ctx.fillRect(...bounds.params);}}
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Cursor
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Cursor extends Entity {
constructor({ color, radius }) {
super();_defineProperty(this, "draw",
({ ctx, pointer }) => {
ctx.strokeStyle = this.strokeStyle;
ctx.lineWidth = this.lineWidth;
ctx.beginPath();
ctx.arc(
pointer.position.x,
pointer.position.y,
this.radius,
0,
this.pi2,
true);
ctx.closePath();
ctx.stroke();
});this.radius = this.toValue(radius);this.pi2 = Math.PI * 2;this.lineWidth = this.toValue(2);this.strokeStyle = color;}}
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Pointer
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Pointer {
constructor() {_defineProperty(this, "update",
({ tick }) => {
this.modifier && this.modifier(this, tick);
});this.dpr = window.devicePixelRatio || 1;this.delta;this.lastPosition = null;this.position = new Point(null, null);this.addListeners();}delta() {return this.position.delta(this.lastPosition);}addListeners() {['mousemove', 'touchmove'].forEach((event, touch) => {window.addEventListener(event, e => {// move previous point
const { x: px, y: py } = this.position; // disable the demo modifier if it's been added
if (this.modifier) {this.modifier = null;}if (touch) {e.preventDefault();const x = e.targetTouches[0].clientX * this.dpr;const y = e.targetTouches[0].clientY * this.dpr;if (!this.lastPosition) {this.lastPosition = new Point(x, y);} else {this.lastPosition.moveTo(px, py);}this.position.moveTo(x, y);} else {const x = e.clientX * this.dpr;const y = e.clientY * this.dpr;if (!this.lastPosition) {this.lastPosition = new Point(x, y);} else {this.lastPosition.moveTo(px, py);}this.position.moveTo(x, y);}}, false);});}addPointerModifier(modifier) {this.modifier = modifier;}}
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡/
// Point
//*‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡*/
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
get position() {
return [this.x, this.y];
}
clone() {
return new Point(this.x, this.y);
}
delta(point) {
return [this.x - point.x, this.y - point.y];
}
distance(point) {
const dx = point.x - this.x;
const dy = point.y - this.y;
return Math.sqrt(dx * dx + dy * dy);
}
moveTo(x, y) {
this.x = x;
this.y = y;
return this;
}
move(x, y) {
this.x += x;
this.y += y;
return this;
}
moveAtAngle(angle, distance) {
this.x += Math.cos(angle) * distance;
this.y += Math.sin(angle) * distance;
return this;
}
applyVelocity(velocity) {
this.x += velocity.vx;
this.y += velocity.vy;
return this;
}
angleRadians(point) {
// radians = atan2(deltaY, deltaX)
const y = point.y - this.y;
const x = point.x - this.x;
return Math.atan2(y, x);
}
angleDeg(point) {
// degrees = atan2(deltaY, deltaX) * (180 / PI)
const y = point.y - this.y;
const x = point.x - this.x;
return Math.atan2(y, x) * (180 / Math.PI);
}
rotate(origin, radians) {
// rotate the point around a given origin point
const cos = Math.cos(radians.........完整代码请登录后点击上方下载按钮下载查看
网友评论0