【问题标题】:How can I animate a ball with a background image on the canvas? [duplicate]如何在画布上为带有背景图像的球设置动画? [复制]
【发布时间】:2019-07-13 16:18:47
【问题描述】:

我正在创建一个画布游戏,其中的球会相互反弹。 我希望球有自己的皮肤,其中背景图像放在弧元素上。

当球没有弹跳时,图像剪辑得很好并且是圆形的,就像弧线一样。但是,当我开始为球设置动画时,它根本不会移动,因为剪辑功能不允许重绘图像或弧线。

那时我发现画布中的保存和恢复功能允许在制作动画时使用剪辑方法。

这个问题是图像的一部分没有正确剪辑。动画只有一半是圆形的,另一半是矩形图像。我试过调整图像的位置,但这并没有达到预期的效果。

我不确定为什么代码会出现这样的行为,以及如何修复它,使它只是一个带有图像背景的动画球。

如果有人对此有所了解,或许有解决方案,那将不胜感激。

下面是代码和sn-p:

  const x = document.getElementById('canvas');
  const ctx = x.getContext('2d');
  let slide = 0;
  class Balls {
    constructor(xPos, yPos, radius) {
      this.xPos = xPos;
      this.yPos = yPos;
      this.radius = radius;
      this.imgX = this.xPos - this.radius;
    }
  }
  const img = document.createElement('img');
  img.src = 'https://geology.com/google-earth/google-earth.jpg';
  Balls.prototype.render = function() {
    ctx.save();
    ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI * 2);
    ctx.clip();
    ctx.drawImage(img, this.imgX, this.yPos - this.radius, this.radius * 2, this.radius * 2);

  };
  Balls.prototype.motion = function() {
    this.imgX = this.imgX + 1;
    this.xPos = this.xPos + 1;
  }
  let object = new Balls(100, 100, 25);
  const animate = () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    object.render();
    object.motion();
    ctx.restore();
  }
  setInterval(animate, 50);
body {
  background-color: grey;
}

#canvas {
  background-color: white;
}

#mod {
  border-radius: 100%
}
<!DOCTYPE html>
<html>
<head>
  <title>Page Title</title>
  <script src='practice.js'></script>
  <link rel="stylesheet" type="text/css" href="practice.css">
</head>
<body>
  <canvas id="canvas" height="200" width="800" />
</body>
</html>

【问题讨论】:

    标签: javascript animation html5-canvas prototype javascript-objects


    【解决方案1】:

    您需要调用ctx.beginPath(),否则,每次调用arc() 都会添加到相同且唯一的子路径中。这意味着最后,您将剪裁一条由许多弧线组成的奇怪路径: 5 帧后路径的 ASCII 表示:((((( )

    const x = document.getElementById('canvas');
    const ctx = x.getContext('2d');
    let slide = 0;
    class Balls {
      constructor(xPos, yPos, radius) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.radius = radius;
        this.imgX = this.xPos - this.radius;
      }
    }
    const img = document.createElement('img');
    img.src = 'https://geology.com/google-earth/google-earth.jpg';
    Balls.prototype.render = function() {
      ctx.save();
      // begin a  new sub-path
      ctx.beginPath();
      ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI * 2);
      ctx.clip();
      ctx.drawImage(img, this.imgX, this.yPos - this.radius, this.radius * 2, this.radius * 2);
    
    };
    Balls.prototype.motion = function() {
      this.imgX = this.imgX + 1;
      this.xPos = this.xPos + 1;
    }
    let object = new Balls(100, 100, 25);
    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      object.render();
      object.motion();
      ctx.restore();
      requestAnimationFrame(animate);
    }
    animate();
    body {
      background-color: grey;
    }
    
    #canvas {
      background-color: white;
    }
    
    #mod {
      border-radius: 100%
    }
    &lt;canvas id="canvas" height="200" width="800" /&gt;

    另请注意,对于圆形遮罩,您最好使用合成而不是剪切,合成处理更好的抗锯齿,并且不需要昂贵的保存/恢复。

    const x = document.getElementById('canvas');
    const ctx = x.getContext('2d');
    let slide = 0;
    class Balls {
      constructor(xPos, yPos, radius) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.radius = radius;
        this.imgX = this.xPos - this.radius;
      }
    }
    const img = document.createElement('img');
    img.src = 'https://geology.com/google-earth/google-earth.jpg';
    Balls.prototype.render = function() {
      // begin a  new sub-path
      ctx.beginPath();
      ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI * 2);
      ctx.fill();
      ctx.globalCompositeOperation = 'source-in';
      ctx.drawImage(img, this.imgX, this.yPos - this.radius, this.radius * 2, this.radius * 2);
      ctx.globalCompositeOperation = 'source-over';
    };
    Balls.prototype.motion = function() {
      this.imgX = this.imgX + 1;
      this.xPos = this.xPos + 1;
    }
    let object = new Balls(100, 100, 25);
    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      object.render();
      object.motion();
      requestAnimationFrame(animate);
    }
    animate();
    body {
      background-color: grey;
    }
    
    #canvas {
      background-color: white;
    }
    
    #mod {
      border-radius: 100%
    }
    &lt;canvas id="canvas" height="200" width="800" /&gt;

    【讨论】:

      猜你喜欢
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 2014-08-01
      • 2021-03-14
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多