为什么我的图像不会出现在画布上?

时间:2019-02-15 17:47:13

标签: javascript object html5-canvas prototype drawimage

我想使用原型在它们上绘制许多具有相同图像的不同大小的圆。问题是,圆圈没有显示在其上绘制的图像。

圆圈仍然存在,因为使用笔触时可见,但未绘制图像。在没有原型的情况下,我可以在其中绘制带有图像的弧,但是一旦使用它,它就无法工作。

控制台中没有错误,因此我不清楚我缺少什么。 我曾尝试将事件侦听器移至原型之外,但圆形图像仍未出现。

如果任何人都可以分享他们为什么不起作用的任何见解和解决方案,将不胜感激。

代码如下:

const ctx = document.getElementById('canvas').getContext('2d');
class Balls {
  constructor(xPos, yPos, radius){
    this.xPos = xPos;
    this.yPos = yPos;
    this.radius = radius;
  }
}
Balls.prototype.render  = function(){
  const img = document.createElement('img');
  img.src = 'crystal.jpg';
  ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI*2)
  ctx.stroke();	
  ctx.clip();
  img.addEventListener('onload', function(e){
    ctx.drawImage(img, this.xPos - this.radius, this.yPos - this.radius, 
    this.radius*2, this.radius*2);
  });
};
let object = new Balls(100, 100, 50);
object.render();
<canvas id='canvas'></canvas>

3 个答案:

答案 0 :(得分:1)

您的代码中有两个问题。首先,onload事件应为load。其次,this在事件侦听器函数中是未知的,因此this.radius等都未定义,ctx.drawImage(img, this.xPos - this.radius, this.yPos - this.radius, this.radius*2, this.radius*2)不起作用。

我为this.xPosthis.yPosthis.radius使用了一些变量,这些变量可以在事件侦听器回调函数中使用。 希望这会有所帮助!

const ctx = document.getElementById('canvas').getContext('2d');
class Balls {
  constructor(xPos, yPos, radius) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.radius = radius;
  }
}
Balls.prototype.render = function() {
  const img = new Image();
  img.src = 'https://source.unsplash.com/random';
  var xPos = this.xPos, yPos = this.yPos, radius = this.radius
  ctx.arc(xPos, yPos, radius, 0, Math.PI * 2)
  ctx.stroke();
  ctx.clip();
  img.addEventListener('load', function(e) {
    console.log("load")
    ctx.drawImage(img, xPos - radius, yPos - radius, 
    radius*2, radius*2);
  });
};
let object = new Balls(100, 100, 50);
object.render();
<canvas id='canvas'></canvas>

答案 1 :(得分:1)

在这里,我只是在这里更改了两件事,以使您的代码正常工作。

  1. load用于事件监听器,而不是onload上的应用。
  2. 使用Arrow函数来依赖父上下文而不是动态上下文(this)。

const ctx = document.getElementById('canvas').getContext('2d');
class Balls {
  constructor(xPos, yPos, radius) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.radius = radius;
  }
}
Balls.prototype.render = function() {
  const img = document.createElement('img');
  img.src = 'https://via.placeholder.com/150.png?text=vijay'
  ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI * 2)
  ctx.stroke();
  ctx.clip();
  img.addEventListener('load', (e) => {
    ctx.drawImage(img, this.xPos - this.radius, this.yPos - this.radius,
      this.radius * 2, this.radius * 2);
  });
};
let object = new Balls(100, 100, 50);
object.render();
<canvas id='canvas'></canvas>

答案 2 :(得分:1)

这是加载图像的一种替代方法,该图像更具模块化,如果您要制作游戏,Img类将派上用场。

Off-topic - if you want to load multiple images then you can add a totalLoaded counter to keep track of how many images has been loaded and if the totalLoaded count is equal to totalImages count then you can call a callback which will fire the animationLoop and preloads all the images.

const ctx = document.getElementById('canvas').getContext('2d');

// Img class to provide modular code
class Img {
  constructor(src, x, y, size) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.src = src;
    this.img = new Image();
    this.img.src = this.src;
    this.isLoaded = false;
    this.img.addEventListener('load', (e) => {
      this.isLoaded = true;
      this.draw();
    });
  }

  draw() {
    if (this.isLoaded) {
      ctx.drawImage(this.img, this.x, this.y, this.size, this.size);
    }
  }
}

class Balls {
  constructor(xPos, yPos, radius) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.radius = radius;
  }
}
Balls.prototype.render = function() {
  let imgx = this.xPos - this.radius;
  let imgy = this.yPos - this.radius;
  let imgr = this.radius * 2;
  let url = 'https://via.placeholder.com/150.png?text=Better';
  const img = new Img(url, imgx, imgy, imgr);
  ctx.arc(this.xPos, this.yPos, this.radius, 0, Math.PI * 2)
  ctx.stroke();
  ctx.clip();
  img.draw();
};
let object = new Balls(100, 100, 50);
object.render();
<canvas id='canvas'></canvas>