canvas函数imageObj onload较慢并且不返回任何内容

时间:2013-06-13 15:21:42

标签: javascript html5 google-maps-api-3 canvas

我在javascript和google地图上创建了一个使用外部图标的功能,并使用html5画布重绘它,然而,当我使用 imageObj.onload 时,加载图标的原因,功能不是返回任何东西,然后我删除该函数并发送结果,但它不是使用图标和画布的正确形式 我的代码是

function getIconMarker(course, speed){
        course = parseFloat (course) * 0.01745327777;
        if (parseInt(speed) != 0) {
            imageIcon = '{% static "markers/onmove.gif" %}';
        } else {
            imageIcon = '{% static "markers/onstop.png" %}';
        }
        var elemento = document.createElement("canvas");
        elemento.width = 80;
        elemento.height = 80;
        if(elemento && elemento.getContext){
            var context = elemento.getContext('2d');
            if(context){
                var imageObj = new Image();
                imageObj.src = imageIcon;
                //imageObj.onload = function(){
                    //console.debug('image loaded');
                    context.save();
                    context.translate(imageObj.width, imageObj.height);
                    context.rotate(course);
                    context.drawImage(imageObj, -(imageObj.width/2), -(imageObj.height/2));
                    context.restore();
                    //console.debug(elemento.toDataURL());
                    return elemento.toDataURL();
                //} 
                console.debug('image no loaded');
            }
            console.debug('no context created');
        }
        console.debug('no context enblaed');
        //return imageIcon;
    }

2 个答案:

答案 0 :(得分:1)

图片加载是异步的,因此您拥有来进行链接调用。这样做的一种方法是使用事件创建一个调用链。

一个调用链是用一个函数启动的,完成后调用链中的下一个函数,完成下一个函数后再等等。

主要区别在于您将代码划分为函数而不是只有一个全局函数。

典型的同步代码如下所示:

Start:
result = doSomething()
result = doSomethingElse()
result = calc something
result = andDoSomeMore()
...
Finished!

这很好用,因为在当前函数完成之前不会调用下一个函数。

虽然异步方法如下所示:

function doSomething()           then call doSomethingElse(result)
function doSomethingElse(result) then call calc function(result)
function calcSomething(result)   calc something, call andDoSomeMore(result)
function andDoSomeMore(result)   Finished!

Start: doSomething()

使用异步方法在全局上下文中发生的唯一事情是启动链的第一部分,因为我们必须等待一些事情才能继续。当我们在函数内部收到事件时,我们将知道何时继续。我们不像处理同步方法那样处理来自异步函数的任何结果。异步函数不能返回任何数据。他们需要传递数据作为参数,以便在事件发生时需要的数据调用下一个函数。

全局上下文基本上通常只是为了保存我们链所需的函数和变量并启动它。

例如,您可以修改函数以进行回调,一个用于成功,一个用于出错。当图像加载事件结束时,它将调用那些将进入链中下一步的函数:

function getIconMarker(course, speed, callback, callbackError){
    // other code snipped...

    if(elemento && elemento.getContext){
        var context = elemento.getContext('2d');
        if(context){
            var imageObj = new Image();
            imageObj.onload = function(){
                console.debug('image loaded');
                context.save();
                context.translate(imageObj.width, imageObj.height);
                context.rotate(course);
                context.drawImage(imageObj, -(imageObj.width/2), -(imageObj.height/2));
                context.restore();

                //use a callback to trigger next function with image as argument
                callback(elemento.toDataURL());
            }
            imageObj.onerror = callbackError;
            imageObj.src = imageIcon; // start loading image and return (void)
        }
    }
}

现在我们可以传递我们做的数据作为函数的参数。回调函数可以如下所示:

function callbackSuccess(dataUri) {
    // we got an image
    //perform next step, upload etc.
    //...
}

对于错误处理程序(在典型情况下可能很常见) - (给它一个更多的逻辑名称,即适合下一步的名称),例如:

function callbackError(errorEvent) {
    console.log(errorEvent);
    alert('An error occurred loading an image');
}

这一切都可以通过调用:

getIconMarker(course, speed, callbackSuccsess, callbackError);

getIconMarker将立即返回,但在准备好后,它会将数据传递给下一个函数。

答案 1 :(得分:-2)

画布的toDataURL函数不适用于图像。 无法在画布上绘制图像并使用toDataURL函数将其转换为URL。 只有画布上绘制的矩形,线条和其他形状等元素才能使用函数toDataURL转换为URL数据。我想你必须找到另一种方式。