繁体   English   中英

如何实现 object 旋转 animation?

[英]How to implement object rotation animation?

有一个落球代码https://jsfiddle.net/d1e8x7wk/

使用 canvas 生成

代码也添加到了这个编辑器

 window.addEventListener('load', () => { //--------------------------------------- // Set up ball options //--------------------------------------- const imgBalls = [ 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png', 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png', 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png', 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png', 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png', 'https://cdn.iconscout.com/icon/premium/png-256-thumb/basketball-2500972-2093649.png' ] let ballCount = imgBalls.length, // How many balls DAMPING = 0.4, // Damping GRAVITY = 0.01, // Gravity strength SPEED = 5, // Ball speed ballAdditionTime = 100, // How fast are balls added ballSrc = imgBalls, // Ball image source topOffset = 400, // Adjust this for initial ball spawn point xOffset = 0, // left offset yOffset = 0, // bottom offset ballDensity = 20, // How dense are the balls ball_1_size = 200, // Ball 1 size ball_2_size = 180, // Ball 2 size ball_3_size = 62, // Ball 6 size canvasWidth = 1500, // Canvas width canvasHeight = 1000, // Canvas height stackBall = true, // Stack the balls (or false is overlap) ballsLoaded = 0, stopAnimation = false; //--------------------------------------- // Canvas globals //--------------------------------------- let canvas, ctx, TWO_PI = Math.PI * 2, balls = [], vel_x, vel_y; let rect = { x: 0, y: 0, w: canvasWidth, h: canvasHeight }; //--------------------------------------- // do the animation //--------------------------------------- window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function(callback) { window.setTimeout(callback, ballAdditionTime); }; //--------------------------------------- // set up the ball //--------------------------------------- const Ball = function(x, y, radius, num) { this.x = x; this.y = y; this.px = x; this.py = y; this.fx = 0; this.fy = 0; this.radius = radius; this.num = num; this.angle = 0; // Different ball sizes let random = Math.round(Math.random() * imgBalls.length) if (random === 0) { this.width = ball_1_size; this.height = ball_1_size; if (stackBall) { this.radius = ball_1_size / 2; } } else if (random === 1 || random === 2) { this.width = ball_2_size; this.height = ball_2_size; if (stackBall) { this.radius = ball_2_size / 2; } } else { this.width = ball_3_size; this.height = ball_3_size; if (stackBall) { this.radius = ball_3_size / 2; } } ctx.rotate(this.angle * Math.PI / 180); }; //--------------------------------------- // Apply the physics //--------------------------------------- Ball.prototype.apply_force = function(delta) { delta *= delta; this.fy += GRAVITY; this.x += this.fx * delta; this.y += this.fy * delta; this.fx = this.fy = 0; }; //--------------------------------------- // Newtonian motion algorithm //--------------------------------------- Ball.prototype.velocity = function() { var nx = this.x * 2 - this.px; var ny = this.y * 2 - this.py; this.px = this.x; this.py = this.y; this.x = nx; this.y = ny; }; //--------------------------------------- // Ball prototype //--------------------------------------- Ball.prototype.draw = function(ctx) { img = new Image(); img.src = imgBalls[this.num]; if (stackBall) { ctx.drawImage( img, this.x - this.radius - xOffset, this.y - this.radius - xOffset, this.width, this.height ); } else { ctx.drawImage( img, this.x - xOffset, this.y - yOffset, this.width, this.height ); } }; //--------------------------------------- // resolve collisions (ball on ball) //--------------------------------------- let resolve_collisions = function(ip) { let i = balls.length; while (i--) { let ball_1 = balls[i]; let n = balls.length; while (n--) { if (n == i) continue; let ball_2 = balls[n]; let diff_x = ball_1.x - ball_2.x; let diff_y = ball_1.y - ball_2.y; let length = diff_x * diff_x + diff_y * diff_y; let dist = Math.sqrt(length); let real_dist = dist - (ball_1.radius + ball_2.radius); if (real_dist < 0) { let vel_x1 = ball_1.x - ball_1.px; let vel_y1 = ball_1.y - ball_1.py; let vel_x2 = ball_2.x - ball_2.px; let vel_y2 = ball_2.y - ball_2.py; let depth_x = diff_x * (real_dist / dist); let depth_y = diff_y * (real_dist / dist); ball_1.x -= depth_x * 0.5; ball_1.y -= depth_y * 0.5; ball_2.x += depth_x * 0.5; ball_2.y += depth_y * 0.5; if (ip) { let pr1 = (DAMPING * (diff_x * vel_x1 + diff_y * vel_y1)) / length; let pr2 = (DAMPING * (diff_x * vel_x2 + diff_y * vel_y2)) / length; vel_x1 += pr2 * diff_x - pr1 * diff_x; vel_x2 += pr1 * diff_x - pr2 * diff_x; vel_y1 += pr2 * diff_y - pr1 * diff_y; vel_y2 += pr1 * diff_y - pr2 * diff_y; ball_1.px = ball_1.x - vel_x1; ball_1.py = ball_1.y - vel_y1; ball_2.px = ball_2.x - vel_x2; ball_2.py = ball_2.y - vel_y2; } } } } }; //--------------------------------------- // Bounce off the walls //--------------------------------------- let check_walls = function() { let i = balls.length; while (i--) { let ball = balls[i]; if (ball.x < ball.radius) { let vel_x = ball.px - ball.x; ball.x = ball.radius; ball.px = ball.x - vel_x * DAMPING; } else if (ball.x + ball.radius > canvas.width) { vel_x = ball.px - ball.x; ball.x = canvas.width - ball.radius; ball.px = ball.x - vel_x * DAMPING; } // Ball is new. So don't do collision detection until it hits the canvas. (with an offset to stop it snapping) if (ball.y > 100) { if (ball.y < ball.radius) { let vel_y = ball.py - ball.y; ball.y = ball.radius; ball.py = ball.y - vel_y * DAMPING; } else if (ball.y + ball.radius > canvas.height) { vel_y = ball.py - ball.y; ball.y = canvas.height - ball.radius; ball.py = ball.y - vel_y * DAMPING; } } } }; //--------------------------------------- // Add a ball to the canvas //--------------------------------------- let add_ball = function(num) { let x = Math.random() * canvas.width; let y = Math.random() * canvas.height; let r = 30 + Math.random() * ballDensity; let diff_x = x; let diff_y = y; let dist = Math.sqrt(diff_x * diff_x + diff_y * diff_y); balls.push(new Ball(x, y, r, num)); }; //--------------------------------------- // iterate balls //--------------------------------------- let update = function() { let iter = 1; let delta = SPEED / iter; while (iter--) { let i = balls.length; while (i--) { balls[i].apply_force(delta); balls[i].velocity(); } resolve_collisions(); check_walls(); i = balls.length; while (i--) { balls[i].velocity(); let ball = balls[i]; } resolve_collisions(); check_walls(); } ctx.clearRect(0, 0, canvas.width, canvas.height); i = balls.length; while (i--) { balls[i].draw(ctx); } requestAnimFrame(update); }; //--------------------------------------- // Set up the canvas object //--------------------------------------- function doBalls() { stopAnimation = false; canvas = document.getElementById("balls"); ctx = canvas.getContext("2d"); let $canvasDiv = document.querySelector(".section"); function respondCanvas() { canvas.height = $canvasDiv.clientHeight; canvas.width = $canvasDiv.clientWidth; ctx.clearRect(0, 0, canvas.width, canvas.height); } respondCanvas(); ballAdd(); } function ballAdd() { let count = 0; let timer = setInterval(function() { addBallTimer(); }, 100); let addBallTimer = function() { add_ball(count % ballCount); count++; if (count === ballCount) { stopTimer(); } }; let stopTimer = function() { clearInterval(timer); }; update(); } doBalls(); });
 .section { position: relative; top: 0; left: 0; width: 100vw; height: 100vh; background-color: #000; }
 <div class="section"> <canvas id="balls"></canvas> </div>

我正在尝试让球旋转

const Ball = function(x, y, radius, num) {
        this.x = x;
        this.y = y;
        this.px = x;
        this.py = y;
        this.fx = 0;
        this.fy = 0;
        this.radius = radius;
        this.num = num;
        this.angle = 0;

        // Different ball sizes
        let random = Math.round(Math.random() * imgBalls.length)

        if (random === 0) {
  this.width = ball_1_size;
  this.height = ball_1_size;
  if (stackBall) {
    this.radius = ball_1_size / 2;
  }
} else if (random === 1 || random === 2) {
  this.width = ball_2_size;
  this.height = ball_2_size;
  if (stackBall) {
    this.radius = ball_2_size / 2;
  }
} else {
  this.width = ball_3_size;
  this.height = ball_3_size;
  if (stackBall) {
    this.radius = ball_3_size / 2;
  }
}

        ctx.rotate(this.angle * Math.PI / 180);
      };

看完资料后,

我写了这段代码,但它对我不起作用

ctx.rotate(this.angle * Math.PI / 180);

我一定误解了如何做到这一点,告诉我如何正确旋转球

提前致谢

您将需要

  1. 在代码中的某个点增加角度
  2. 在每次 drawImage 调用之前应用旋转变换以围绕每个球中心旋转
ctx.save();
ctx.translate(+this.x, +this.y);
ctx.rotate(this.angle++ * Math.PI / 180);
ctx.translate(-this.x, -this.y);
ctx.drawImage
ctx.restore()

ctx.save()ctx.restore()以在每次绘制调用后恢复 canvas 变换。

请阅读https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rotate#rotating_a_shape_around_its_center以了解将转换应用于 Canvas 的详细信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM