图像无法加载并且不显示在HTML画布上

4
我正在开发一个网站,当加载时,它会显示从HTML画布元素编译的图像。我的问题是,我无法确定何时加载图像以将其绘制到画布上或者如何强制在进行下一步之前加载图像。我已经查看了关于此主题的先前帖子,并尝试了许多不同的解决方案,但对我来说都没有起作用。
我正在使用web2py,因此我使用一些在服务器端运行的Python助手。
当我使用这个时:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
image1.onload = function() {
    context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};

由于图片没有加载,onload函数不会执行任何操作,因此跳过它。我也尝试在设置源之前放置onload函数,但是图片仍然未被绘制。

我已经尝试了:

//code from above
if(image1.completed) {
    context.drawImage(image1, 0, 0, canvas.width, canvas.height);
}

但是我也遇到了同样的问题。

我还考虑过可能是图像在加载时产生了错误。为了捕捉这个问题,我写了以下代码:

//code from above
image1.onerror = function() {
    console.log('error');
}

但是图像源是好的,图像没有出错,只是加载需要很长时间。有没有办法在将图像绘制到画布之前等待它加载完成?

为了具体说明:

我的HTML代码如下:

<div id="profile-container" class="container-fluid">
    <h1>My Notes</h1>
    <div id="empty-orders" class="column-wrapper disable" style="padding-top: 5px; margin: 0 38%;">
        <h3>Create a Note and it will appear here</h3>
        <button class="btn btn-lg btn-outline">{{=A('GET STARTED', _href=URL('default', 'canvas_board_print'))}}</button>
    </div>
    <div id="loading" class="column-wrapper">
        <i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
    </div>
    <div id="row1" class="row">

    </div>
</div>

我的javascript代码如下所示:
function showOrders(note_orders) {
    var orders = note_orders;
    //console.log(orders);
    var row_num = 1;
    var node_num = 1;
    if(orders.length > 0) {
        for (var i = 0; i != orders.length; i++) {
            orders[i].border = JSON.parse(orders[i].border);
            orders[i].image_retouching = JSON.parse(orders[i].image_retouching);
            orders[i].shipping_info = JSON.parse(orders[i].shipping_info);
            var new_node = $("<div>", {id: "node" + node_num, "class": "col-xs-3 node-wrapper"});
            var new_canvas = $('<canvas>', {id: "canvas" + node_num, style: 'display: none'});
            var new_image = $('<img>', {id: "note_prev" + node_num, 'class': 'img-responsive'});
            $('#row' + row_num).append(new_node);
            $('#node'+ node_num).append(new_canvas).append(new_image).append(processOrders(orders[i], node_num));
            node_num++;
            if (i != 0 && (i + 1) % 4 == 0) {
                row_num++;
                var new_row = $("<div>", {id: "row" + row_num, "class": "row"});
                $(' #profile-container ').append(new_row);
            }
        }
        $(' #loading ').addClass('disable');
    } else {
        $(' #loading ').addClass('disable');
        $(' #empty-orders ').removeClass('disable');
    }
}
function processOrders(curr_order, node_num) {
    var canvas = document.getElementById('canvas' + node_num);
    var context = canvas.getContext('2d');

    var image1 = new Image();
    image1.src = curr_order.image_url;
    canvas.width = image1.naturalWidth;
    canvas.height = image1.naturalHeight;
    if(image1.complete) {
        context.drawImage(image1, 0, 0, canvas.width, canvas.height);
        if(curr_order.border.style == 'color_wrap') {
            document.getElementById('note_prev' + node_num).style.border = "10px solid " + curr_order.border.color;
        } else if(curr_order.border.style == 'image_wrap') {
            var image_wrap = new Image();
            if(canvas.width > canvas.height) {
                image_wrap.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}';
            } else {
                image_wrap.src = '{{=URL('static', 'images/image-wrap-border-port.png')}}';
            }
            console.log(image_wrap);
            image_wrap.onload = function() {
                context.drawImage(image_wrap, 0, 0, canvas.width, canvas.height);
            };
            image_wrap.onerror = function() {
                console.log('errors');
            }
        }
    }
    document.getElementById('note_prev' + node_num).src = canvas.toDataURL('image/png');
    var node_div = document.createElement('div');
    //Other non-image informantion is appended to node_div
    return node_div;
}

我的问题是在绘制image_wrap时出现了问题,而不是像上面的例子中的image1。代码中的image1可以正常绘制,但是当绘制到画布上时,image_wrap不会出现。

我修复了它!!!

我将创建image_Wrap变量的位置与创建image1变量的位置一起移动。

function processOrders(curr_order, node_num) {
    var canvas = document.getElementById('canvas' + node_num);
    var context = canvas.getContext('2d');

   var image1 = new Image();
   var image_wrap = new Image();
   image1.src = curr_order.image_url;
   canvas.width = image1.naturalWidth;
   canvas.height = image1.naturalHeight;
   if(image1.complete) {
       context.drawImage(image

我原本认为这不是个好主意,因为我不想创建额外的变量,即使它们不会被使用,但我猜这样做解决了问题。

3个回答

4

使用您的代码,我能够加载图像。

您能否确认在加载图像时未出现错误?

(寻求澄清: 发布答案以演示运行代码片段)

更新: 添加了一种粗略的方法,在加载图像后等待一秒钟再将其绘制到画布上。

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var image1 = new Image();

image1.src = 'http://lorempixel.com/400/200/sports/1/';
image1.onload = function() {
  // you could draw the image right away
  // ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);

  // OR
  // You could wait for an extra second before drawing the image (hackish, I know)
  setTimeout(function() {
    ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
  }, 1 * 1000); // 1 second (in milliseconds)
};
<h2>canvas</h2>
<canvas id='canvas'>
</canvas>
<hr/>


谢谢,但问题是一个打字错误。在我的实际代码中,我已经正确地书写了它。 - nightwuffle
@nightwuffle 你的代码应该可以工作了-看到我的运行片段了吗-你能否用固定的URL替换你的变量并测试一下呢? - blurfus
图片没有产生任何错误。我用我的URL替换了您在示例中使用的URL,但仍然无法工作。我将在我的帖子中更新更具体的有关我的代码和问题的信息。 - nightwuffle
1
我解决了。我将image_wrap变量的声明与image1变量的声明一起向上移动,这样就解决了。不过还是谢谢你的帮助。 - nightwuffle
随意将其添加为答案,以造福他人 :) - blurfus

2
在设置图片的 src 属性之前,先设置 onload 函数。很可能是因为图片在 onload 函数被设置前就已经开始加载了。
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.onload = function() {
    context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'

1

context.drawImage的第一个参数是您要绘制的图像,第二个和第三个参数是上下文中的位置....

context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

剩余的参数允许您缩放图像。
建议您尝试...
image1.onload = function() { context.drawImage(image1,0,0); }

谢谢,但我在问题中打错了一个字。在我的代码中它是正确的。我已经尝试了你建议的方法,它在我的问题中,但对我不起作用。我也尝试过在onload之后设置图像源,但它仍然跳过它。 - nightwuffle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接