我目前正在学习JavaScript OOP。在这里我创建了一个名为person的构造函数。我给了它一个原型属性来绘制画布上每个新人的脸(我的意思是一个图像)。我已经介绍了不同的警报命令来检查它是否正常工作。我认为我做的一切都是正确的,但出于某种原因,图像并没有在画布上绘制。
的JavaScript
function draw(){
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 600;
canvas.style.border = "1px solid black";
var person = function (name, age) {
this.name = name;
this.age = age;
};
person.prototype.drawit = function(src, xpos, ypos, width, height) {
this.src = src;
this.xpos = xpos;
this.ypos = ypos;
this.width = width;
this.height = height;
var img = new Image();
img.src = this.src;
ctx.drawImage(img, this.xpos, this.ypos, this.width, this.height);
};
var person1 = new person("winsteen", "14");
person1.drawit("lol1", 200, 200, 40, 50);
alert(person1.age);
alert(person1.src);
}
window.onload = draw;
HTML
<canvas id="mycanvas"></canvas>
答案 0 :(得分:2)
这是因为您的图像需要一些时间来加载,并且在加载之前绘制图像。设置img.src
后,将img.onload
设置为执行绘图的函数。一旦图像加载并准备好绘制,就会异步调用此函数。
如果你想使用this
关键字,你需要绑定你的负载处理程序,因为,就像保罗说的那样,它会引用图像。
img.onload = drawIt.bind(this);
function drawIt(){
// Your drawing method, doing nothing but drawing the image to the canvas.
}
我注意到你的代码中有很多其他东西你可以改变。目前很多代码都是多余的,您不需要在drawIt
方法中传递xpos,ypos,width,height等。它应该设置/存储在对象构造函数中,因此不带参数调用drawIt方法,并根据存储在对象中的值绘制它。
如果您想要一种设置这些值的方法,请使用另一种方法来设置它们。
设置/加载图像也是如此。您不想创建新图像并在每次绘制时加载它。制作一个单独的&#34; loadImage&#34;加载图像并在加载图像后调用drawIt的方法(如上例所示)。
何时使用bind()
:
您希望使用this
关键字来访问实例变量并创建在许多不同对象上工作相同的函数,因为&#39; this.width&#39;是指Person.width
或Street.width
或基本上任何宽度,具体取决于函数的上下文。该方法保持不变,this
将发生变化。
但是如果你使用事件监听器this
可能并不总是像你期望的那样。 bind()
是一个可以在任何函数上使用的方法,它会永久性地将此函数替换为始终在您提供的上下文中作为{{1}的第一个参数执行 }。
换句话说:您创建函数的新副本,其中bind()
永久设置为特定对象。在这种情况下,它将是你的人。
答案 1 :(得分:1)
<img>
的处理程序内,this
将是<img>
。进行一些重构,你最终会得到这样的结果:
(function () { // Immediately-invoked_function_expression (IIFE) keeps
// global namespace clean - see
// <https://en.wikipedia.org/wiki/Immediately-invoked_function_expression>.
function draw() {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 600;
canvas.style.border = "1px solid black";
function Person(name, age) { // Constructors usually start with a capital letter
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person // Good to let instances know who they are
};
Person.prototype.drawit = function (src, dx, dy, dw, dh) {
var img;
this.src = src;
// Etc. if you want to store these
img = new Image();
img.addEventListener('load', function () {
// `this` here means `img`, access the other values directly
// from their variables.
ctx.drawImage(this, dx, dy, dw, dh);
});
img.src = src; // Initiate image load
};
// Finished setup, now use
var person1 = new Person("Winsteen", "14");
person1.drawit("lol1", 200, 200, 40, 50);
}
window.addEventListener('load', draw); // Safe wait for page load
}()); // Invoke the IIFE