javascript - 在同一 Canvas 中顺时针旋转一个轮子,逆时针旋转另一个轮子

标签 javascript html user-interface canvas html5-canvas

嘿,我在 Canvas 上有两个圆形图像

我想要这两件事:

  1. 当我们点击按钮wheel1时,我想将左轮顺时针旋转到45度并停止。
  2. 当我们点击按钮wheel2时,我想将右轮逆时针旋转到45度并停止。

我已经实现了第一个目标。 但我今天一整天都在尝试,但我无法弄清楚如何才能实现第二点。 当我单击第二个按钮时,左轮停止旋转,右轮在整个 Canvas 中旋转。

如何将右轮逆时针旋转到45度?还有其他有效的方法来实现我已经实现的问题中的部分吗?

最佳答案

  • 仅加载图像一次。无需每次需要绘制图像时都加载图像。此外,两个轮子都是相同的图像,因此您只需要图像的一份副本。

  • 使用 requestAnimationFrame 为 Canvas 内容设置动画。

  • 仅获取 Canvas 上下文一次。不需要每一帧都获取它。

  • 在没有必要时避免更改 Canvas 大小,例如设置 Canvas 宽度或高度,即使相同的值会重置整个 2D 上下文状态。

  • 不要重复相同的代码。除了位置和旋转之外,车轮几乎相同。定义一个描述轮子的对象,并为两个轮子创建该对象,仅设置使它们唯一的属性。

  • 你真的需要 jQuery 吗?这只是膨胀会减慢你的页面速度,而且对于你加载的所有额外的 javascript 行,你只调用了它两次。使用 jQuery 已不再重要,现代浏览器 API 更快、更强大。不要落后。

示例

使用上述要点编写代码的示例。

const wheelImg = new Image;
wheelImg.src = "https://www.freeiconspng.com/uploads/car-wheel-png-image-free-download--car-wheel-png-image-free--11.png";
canvas.width = innerWidth - 30;
canvas.height = innerHeight - 40;
const ctx = canvas.getContext("2d");
const wheelScale = 0.4;  // scales the wheels
const rotateCount = 100; // frames (@60 per second)
var activeWheelCount = 0; // to track if any wheels are active

// when the image has loaded set up click events and draw the first frame
wheelImg.addEventListener("load",() => { 
    requestAnimationFrame(mainLoop)
    clockwiseBtn.addEventListener("click",() => wheels[0].start(Math.PI / 2));
    antiClockwiseBtn.addEventListener("click",() => wheels[1].start(-Math.PI / 2));
    }
    ,{once:true}
);

// defines a single wheel
const wheel = (x,y,rot) => ({
    x,y,rot,
    rotTarget: rot,
    counter: 0,
    start(ang) {   // command a wheel to turn 
      if (!this.counter ) {  // make sure not already turning
          this.counter = rotateCount;
          this.rotTarget += ang;
          if (!activeWheelCount) { requestAnimationFrame(mainLoop) } // start the
                                                                     // animation is no wheel
                                                                     // is active
          activeWheelCount ++;
      }
    },
    update() {  // update the wheel animation counter
        this.counter += this.counter > 0 ? -1 : 0;
        if (this.counter === 0) {  this.rot = this.rotTarget }
        else { activeWheelCount += 1 } // count this wheel as an active wheel
    },
    draw() { // draw the wheel
        const r = (1 - (this.counter / rotateCount))  * (this.rotTarget - this.rot) + this.rot;
        ctx.setTransform(wheelScale, 0, 0, wheelScale, this.x, this.y);
        ctx.rotate(r);
        ctx.drawImage(wheelImg, -wheelImg.width / 2, -wheelImg.height / 2);

    }
});
const wheels = [wheel(90,80, 0), wheel(350,80,0)]; // create two wheels
 
function mainLoop() {  // animates wheels
    activeWheelCount = 0;
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
    wheels.forEach(wheel => wheel.update());
    wheels.forEach(wheel => wheel.draw());
    if (activeWheelCount) {
        requestAnimationFrame(mainLoop);
    }
}
#canvas {
  border:solid 1px black;
  position:absolute;
  top:30px;
  left:0px;
}
  <canvas id="canvas"></canvas>
  <button id='clockwiseBtn'>Wheel1</button>
  <button id='antiClockwiseBtn'>Wheel2</button>

关于javascript - 在同一 Canvas 中顺时针旋转一个轮子,逆时针旋转另一个轮子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59669879/

相关文章:

css - 本应占用 "rest of the page"的div在ie中扩展到页面之外

android - Android 中的动画滤色器

linux - Windows 上的 GUI 在联网的 Linux 机器上运行 Linux 脚本?

javascript - OS X 和 iOS Safari history.replaceState 限制抛出 SecurityError : DOM Exception 18

javascript - window.onload 未在页面刷新时运行

html - 如何让多个图像自动调整大小并在 div 中保持居中

html - 为什么我的导航栏不会在页面中心下拉菜单?

iphone - iPhone 应用程序中的收件人栏

javascript - 如何在我的两个 Electron 应用程序窗口上放置一个主题(深色/浅色模式)?

javascript - Bootstrap 下拉菜单不适用于标准 JS 和 CSS