【问题标题】:Scaling HTML5 Canvas Image缩放 HTML5 画布图像
【发布时间】:2015-05-07 18:11:30
【问题描述】:

构建一个网页,我试图在该网页上将图像设置为主画布的背景。实际图像是 1600x805,我正在尝试对应用程序进行编码,以便根据用户屏幕的尺寸放大或缩小图像。在Prime.js 中,我有一个对象来设置位于index.html 中的应用程序的canvas 元素的属性。这是该对象的代码:

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);
        }
    };

像这样的外部对象与index.html 中的元素交互的主要接口是home.js。以下是那里发生的事情:

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

出于某种原因,我对上下文的 drawImage 函数的调用仅从图像的左上角裁剪,并将其放大到用户屏幕的大小。为什么我看不到图像的其余部分?

【问题讨论】:

    标签: javascript html oop canvas scale


    【解决方案1】:

    问题是在您调用 setInterval 时图像可能还没有完成加载。如果图像未正确加载和解码,则 drawImage 将abort its operation

    如果图像尚未完全解码,则不绘制任何内容

    在尝试绘制之前,您需要确保图像已加载。使用图像的onload 处理程序执行此操作。此操作是异步的,因此这意味着您还需要处理回调(或承诺):

    在背景对象中你需要提供一个图片加载的回调,例如:

    ...
    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';
        }
    },
    ...
    

    现在设置背景后,等待回调,然后继续 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);
        };
    

    如果您想绘制缩放以适合画布的完整图像,您可以简化调用,只需提供新大小(并且 this.globalCanvasMain.x/y 似乎没有定义?):

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

    我建议您使用requestAnimationFrame 绘制图像,因为这将与显示器更新同步。

    还记得为图像对象上的onerror/onabort 提供回调。

    【讨论】:

      【解决方案2】:

      setInterval 函数存在问题。您没有提供正确的功能参考。代码

      setInterval(prime.drawAll(), 25);
      

      只执行一次prime.drawAll,结果只渲染了此时正在加载的图像的一小部分。

      正确的代码应该是:

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

      【讨论】:

      • @dfsq- 几乎可以肯定这会起作用,但没有改变。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-05
      • 2012-12-06
      • 2014-01-04
      • 1970-01-01
      • 2014-02-16
      • 2016-11-15
      相关资源
      最近更新 更多