canvas实现鼠标跟随模拟物理绳子甩动交互效果代码
代码语言:html
所属分类:其他
代码描述:canvas实现鼠标跟随模拟物理绳子甩动交互效果代码
代码标签: canvas 鼠标 跟随 模拟 物理 绳子 甩动 交互
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body{ background-color:#1A1B1F; } #container{ max-width:800px; height:480px; background-color:black; margin: 0 auto; -webkit-box-sizing::border-box; border-style: solid; border-color: white; } #container p{ color:white; margin-left:25px; } </style> </head> <body> <div id="container"> <canvas id="canvas" width="800" height="480"></canvas> <p>Verlet Physics Rope (move the mouse!)</p> </div> <script > //A small scaffold specifically to help me design code pen interactions //Math extensions Math.lerp = (first, second, percentage) => { return first + (second - first) * percentage; }; Math.clamp = (value, min, max) => { return value < min ? min : value > max ? max : value; }; class Vector2 { static zero() { return { x: 0, y: 0 }; } static sub(a, b) { return { x: a.x - b.x, y: a.y - b.y }; } static add(a, b) { return { x: a.x + b.x, y: a.y + b.y }; } static mult(a, b) { return { x: a.x * b.x, y: a.y * b.y }; } static scale(v, scaleFactor) { return { x: v.x * scaleFactor, y: v.y * scaleFactor }; } static mag(v) { return Math.sqrt(v.x * v.x + v.y * v.y); } static normalized(v) { const mag = Vector2.mag(v); if (mag === 0) { return Vector2.zero(); } return { x: v.x / mag, y: v.y / mag }; }} class App { constructor( window, canvas, context, updateHandler, drawHandler, frameRate = 60) { this._window = window; this._canvas = canvas; this._context = context; this._updateHandler = updateHandler; this._drawHandler = drawHandler; this._frameRate = frameRate; this._lastTime = 0; this._currentTime = 0; this._deltaTime = 0; this._interval = 0; this.onMouseMoveHandler = (x, y) => {}; this.onMouseDownHandler = (x, y) => {}; this.start = this.start.bind(this); this._onMouseEventHandlerWrapper = this._onMouseEventHandlerWrapper.bind( this); this._onRequestAnimationFrame = this._onRequestAnimationFrame.bind(this); } start() { this._lastTime = new Date().getTime(); this._currentTime = 0; this._deltaTime = 0; this._interval = 1000 / this._frameRate; this._canvas.addEventListener( "mousemove", e => { this._onMouseEventHandlerWrapper(e, this.onMouseMoveHandler); }, false); this._canvas.addEventListener( "mousedown", e => { this._onMouseEventHandlerWrapper(e, this.onMouseDownHandler); }, false); this._onRequestAnimationFrame(); } _onMouseEventHandlerWrapper(e, callback) { let element = this._canvas; let offsetX = 0; let offsetY = 0; if (element.offsetParent) { do { offsetX += element.offsetLeft; offsetY += element.offsetTop; } while (element = element.offsetParent); } const x = e.pageX - offsetX; const y = e.pageY - offsetY; callback(x, y); } _onRequestAnimationFrame() { this._window.requestAnimationFrame(this._onRequestAnimationFrame); this._currentTime = new Date().getTime(); this._deltaTime = this._currentTime - this._lastTime; if (this._deltaTime > this._interval) { //delta time in seconds const dts = this._deltaTime * 0.001; this._updateHandler(dts); this._context.clearRect(0, 0, this._canvas.width, this._canvas.height); this._drawHandler(this._canvas, this._context, dts); this._lastTime = this._currentTime - this._deltaTime % this._interval; } }} //each rope part is one of these //uses a high precison varient of Störmer–Verlet integration //to keep the simulation consistant otherwise it would "explode"! class RopePoint { //integrates motion equations per node without taking into account relationship //with other nodes... static integrate(point, gravity, dt, previousFrameDt) { point.velocity = Vector2.sub(point.pos, point.oldPos); point.oldPos = { ...point.pos }; //drastically improves stability let timeCorrection = previousFrameDt != 0.0 ? dt / previousFrameDt : 0.0; let accel = Vector2.add(gravity, { x: 0, y: point.mass }); const velCoef = timeCorrection * point.damping; const accelCoef = Math.pow(dt, 2); point.pos.x += point.velocity.x * velCoef + accel.x * accelCoef; point.pos.y += point.velocity.y * velCoef + accel.y * accelCoef; } //apply constraints related to other nodes next to it //(keeps each node within distance) static constrain(point) { if (point.next) { const delta = Vector2.sub(point.next.pos, point.pos); .........完整代码请登录后点击上方下载按钮下载查看
网友评论0