简体   繁体   English

缩放HTML5画布图像

[英]Scaling HTML5 Canvas Image

Building a web page on which I am trying to set an image as the background of the main canvas. 构建一个网页,在该网页上我试图将图像设置为主画布的背景。 The actual image is 1600x805 and I am trying to code the application so that it will scale the image either up or down, according to the dimensions of the user's screen. 实际的图像是1600x805,我正在尝试对应用程序进行编码,以便它可以根据用户屏幕的尺寸向上或向下缩放图像。 In Prime.js I have an object that sets the properties of the application's canvas element located in index.html . Prime.js我有一个对象,用于设置位于index.html中的应用程序canvas元素的属性。 Here is the code for that object: 这是该对象的代码:

function Prime(w,h){
        if(!(function(){
                    return Modernizr.canvas;
                })){ alert('Error'); return false; };
        this.context = null;
        this.self = this;        
        this.globalCanvasMain.w = w;
        this.globalCanvasMain.h = h;
        this.globalCanvasMain.set(this.self);
        this.background.setBg();
    }

    Prime.prototype = {
        constructor: Prime,
        self: this,
        globalCanvasMain: {
            x: 0,
            y: 0,
            set: function(ref){
                ref.context = document.getElementById('mainCanvas').getContext('2d');
                $("#mainCanvas").parent().css('position', 'relative');
                $("#mainCanvas").css({left: this.x, top: this.y, position: 'absolute'});
                $("#mainCanvas").width(this.w).height(this.h); 
            }
        },
        background: {
            bg: null,
            setBg: function(){
                this.bg = new Image();
                this.bg.src = 'res/background.jpg';
            }
        },
        drawAll: function(){

            this.context.drawImage(this.background.bg, 0,0, this.background.bg.width,this.background.bg.height, 
                                    this.globalCanvasMain.x,this.globalCanvasMain.y, this.globalCanvasMain.w,this.globalCanvasMain.h);
        }
    };

The primary interface through which external objects like this one will interact with the elements in index.html is home.js . home.js是主要接口,像这样的外部对象将通过该接口与index.html的元素进行home.js Here's what happens there: 这里是发生了什么:

$(document).ready(function(){
    var prime = new Prime(window.innerWidth,window.innerHeight);
    setInterval(prime.drawAll(), 25);
});

For some reason, my call to the context's drawImage function clips only the top left corner from the image and scales it up to the size of the user's screen. 出于某种原因,我对上下文的drawImage函数的调用仅裁剪了图像的左上角,并将其缩放到用户屏幕的大小。 Why can I not see the rest of the image? 为什么我看不到其余图像?

There is a problem with the setInterval function. setInterval函数有问题。 You are not providing proper function reference. 您没有提供适当的功能参考。 The code 编码

setInterval(prime.drawAll(), 25);

execute prime.drawAll only once, and as the result only little part of the image which is being loaded at this moment, is rendered. 仅执行一次prime.drawAll ,结果是此时只加载了图像的一小部分。

Correct code should be: 正确的代码应为:

$(document).ready(function(){
    var prime = new Prime(window.innerWidth, window.innerHeight);
    setInterval(function() {
        prime.drawAll();
    }, 25);
});

The problem is that the image has probably not finished loading by the time you call setInterval. 问题在于,在您调用setInterval时,图像可能尚未完成加载。 If the image is not properly loaded and decoded then drawImage will abort its operation : 如果图像未正确加载和解码,则drawImage将中止其操作

If the image isn't yet fully decoded, then nothing is drawn 如果图像尚未完全解码,则不会绘制任何图像

You need to make sure the image has loaded before attempting to draw it. 尝试绘制图像之前,需要确保已加载图像。 Do this using the image's onload handler. 使用图像的onload处理程序执行此操作。 This operation is asynchronous so it means you also need to deal with either a callback (or a promise): 此操作是异步的,因此这意味着您还需要处理回调(或Promise):

In the background object you need to supply a callback for the image loading, for example: 在后台对象中,您需要为图像加载提供回调,例如:

...
background: {
    bg: null,
    setBg: function(callback) {
        this.bg = new Image();
        this.bg.onload = callback;          // supply onload handler before src
        this.bg.src = 'res/background.jpg';
    }
},
...

Now when the background is set wait for the callback before continue to drawAll() (though, you never seem to set a background which means drawImage tries to draw null ): 现在,设置背景后,等待回调,然后继续drawAll()(尽管,您似乎从未设置过背景,这意味着drawImage尝试绘制null ):

$(document).ready(function(){
    var prime = new Prime(window.innerWidth, window.innerHeight);

    // supply a callback function reference:
    prime.background.setBg(callbackImageSet);

    // image has loaded, now you can draw the background:
    function callbackImageSet() {
      setInterval(function() {
        prime.drawAll();
      }, 25);
    };

If you want to draw the complete image scaled to fit the canvas you can simplify the call, just supply the new size (and this.globalCanvasMain.x/y doesn't seem to be defined? ): 如果要绘制缩放为适合画布的完整图像,则可以简化调用,只需提供新的尺寸即可(并且似乎未定义this.globalCanvasMain.x / y?):

drawAll: function(){
    this.context.drawImage(this.background.bg, 0,0, 
                                                   this.globalCanvasMain.w,
                                                   this.globalCanvasMain.h);
}

I would recommend you to use requestAnimationFrame to draw the image as this will sync with the monitor update. 我建议您使用requestAnimationFrame绘制图像,因为这将与监视器更新同步。

Also remember to provide callbacks for onerror / onabort on the image object. 还要记住为图像对象上的onerror / onabort提供回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM