使用方法绘制图像

时间:2014-05-22 18:12:01

标签: javascript oop canvas

我目前正在学习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>

2 个答案:

答案 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.widthStreet.width或基本上任何宽度,具体取决于函数的上下文。该方法保持不变,this将发生变化。

但是如果你使用事件监听器this可能并不总是像你期望的那样。 bind()是一个可以在任何函数上使用的方法,它会永久性地将此函数替换为始终在您提供的上下文中作为{{1}的第一个参数执行 }。

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

答案 1 :(得分:1)

  1. 图像必须先加载才能绘制。
  2. <img>的处理程序内,this将是<img>
  3. 调试时使用高对比度检查,因此您无法获得白色的白色。
  4. 进行一些重构,你最终会得到这样的结果:

    (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