Javascript 使用方法绘制图像

Javascript 使用方法绘制图像,javascript,oop,canvas,Javascript,Oop,Canvas,我目前正在学习JavaScript。在这里,我创建了一个名为person的构造函数。我给它一个原型属性,在画布上画每个新人的脸(我指的是图像)。我引入了不同的警报命令来检查它是否正常工作。我认为我做的每件事都是对的,但由于某种原因,图像没有被画在画布上 JavaScript function draw(){ var canvas = document.getElementById("mycanvas"); var ctx = canvas.getContext('2d');

我目前正在学习JavaScript。在这里,我创建了一个名为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>

这是因为加载图像需要时间,并且在加载图像之前先绘制图像。设置
img.src
后,将
img.onload
设置为执行绘图的函数。一旦图像加载并准备好绘制,就会异步调用此函数

如果要使用
this
关键字,则需要绑定加载处理程序,因为正如Paul所说,否则它将引用图像

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方法时不带参数,并将根据存储在对象中的值进行绘制

如果您想要一种设置这些值的方法,请使用另一种方法来设置它们

设置/加载图像也是如此。您不希望创建新图像并在每次绘制时加载它。创建一个单独的“loadImage”方法,加载图像并在加载图像后调用drawIt(如上面的示例所示)

何时使用
bind()

您希望使用
this
关键字访问实例变量并创建在许多不同对象上工作相同的函数,因为“this.width”指的是
Person.width
Street.width
或基本上任何宽度,具体取决于函数的上下文。方法保持不变,
将更改

但是,如果您使用事件侦听器
,则此
的行为可能并不总是与您预期的一样
bind()
是一种可以在任何函数上使用的方法,它永久性地将此函数替换为一个新函数,该函数将始终在作为
bind()
的第一个参数提供的上下文中执行

换句话说:创建函数的新副本,其中
永久设置为特定对象。在这种情况下,它将是你的人

  • 必须先加载图像,然后才能绘制图像

  • 检查控制台上的处理程序中,有错误吗?它没有给出任何错误。
    “lol1”
    是否是图像的正确相对路径?它似乎没有包含文件扩展名(例如,jpg、png、gif),我一刻也没有考虑过。这一个也没有错误报告。添加.jpg扩展名完美地绘制了图像:)。我使用了img.onload=function(){ctx.drawImage(img,this.xpos,this.ypos,this.width,this.height);}可以吗?它也不起作用。在src之前设置onload,2。在加载处理程序中,
    指的是
    ,3。确保你能真正看到你想要画的东西;i、 e.white on white=invisibleok做了类似这样的事情:img.onload=function(){img.src=this.src;ctx.drawImage(img,this.xpos,this.ypos,this.width,this.height);}仍然没有图像。这是一张黄色笑脸。所以没有机会在这里变为不可见。bind()具体做什么?我在这里第一次遇到它…@user3138436
    bind
    创建函数的副本。副本中的
    this
    的值与
    bind
    的第一个参数的值相同,与调用方式无关。我不认为给他提供了一个副本可复制的解决方案,该解决方案充满了中间javascript概念,如注册事件处理程序,立即执行匿名函数保持全局命名空间干净在他刚开始的时候,他无法理解这一点对他真的有帮助。我很感激。在这里指出了许多新的关键词供他学习:)。感谢大家帮助我。@Winchestro我怀疑OP只是想加载一个“人”,如果他们只是复制/粘贴,而不试图理解正在发生的事情,那么他们就不太可能改变它来做他们想做的一切。我已经加入了一些评论,帮助他们在阅读时指出正确的方向。正如OP所说,他们正在用JavaScript学习OOP,而不是说他们对整个语言都是新手,我希望其他概念(IIFE、事件处理程序)不需要什么新的学习。这就是说,我明白简单的复制/粘贴并不能帮助你学习:(很公平:)我试图根据我在某个特定问题上看到的潜在/兴趣,平衡示例和解释。如果有人显然只是需要一个快速的解决方案(因为js不是我的主要兴趣),我会发布一些工作代码,否则我会尽可能多地解释,并留下尽可能多的内容让他们自己去理解/编写。但我总是好奇其他人是怎么看的,他们在这个网站上的时间比我长,因为我想提高我教授/交流概念的能力:)@Winchestro解释很多,让他们做很多,这很好,但我发现,如果答案不包括任何代码示例,他们可以放弃,不再感兴趣,这可能是一个难以完美的平衡
    (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