0

我的问题是关于在 HTML Canvas 中使用函数进行绘制的。我尝试用 Canvas 绘制“交易卡”来创建游戏。所以我决定编写一个函数来获取所有必要的信息来绘制不同的卡片。对于一张卡 - 没问题。但是如果我尝试在第一张牌上画另一张牌,第一张牌的图像可以通过第二张牌看到。

这是源代码:

function RoundRect(x,y,scale,lvl,mage,headline,text,HP,MP,AtckP,DefP,MDefP){
            //Kartenumriss zeichnen
            context.strokeStyle="rgb(0,0,0)";
            context.fillStyle="rgb(180,180,180)";
            context.lineWidth=2*scale;
            context.beginPath();
            context.moveTo(x+10*scale,y+0*scale);
            context.lineTo(x+90*scale,y+0*scale);
            context.arcTo(x+100*scale,y+0*scale,x+100*scale,y+10*scale,10*scale);
            context.lineTo(x+100*scale,y+110*scale);
            context.arcTo(x+100*scale,y+120*scale,x+90*scale,y+120*scale,10*scale);
            context.lineTo(x+10*scale,y+120*scale);
            context.arcTo(x+0*scale,y+120*scale,x+0*scale,y+110*scale,10*scale);
            context.lineTo(x+0*scale,y+10*scale);
            context.arcTo(x+0*scale,y+0*scale,x+10*scale,y+0*scale,10*scale);
            context.fill();
            context.stroke();
            //innerer Kartenumriss zeichnen
            context.strokeStyle="rgb(0,0,0)";
            context.lineWidth=2*scale;
            context.beginPath();
            context.moveTo(x+20*scale,y+10*scale)
            context.lineTo(x+80*scale,y+10*scale);
            context.arcTo(x+80*scale,y+20*scale,x+90*scale,y+20*scale,10*scale);
            context.lineTo(x+90*scale,y+100*scale);
            context.arcTo(x+80*scale,y+100*scale,x+80*scale,y+110*scale,10*scale);
            context.lineTo(x+20*scale,y+110*scale);
            context.arcTo(x+20*scale,y+100*scale,x+10*scale,y+100*scale,10*scale);
            context.lineTo(x+10*scale,y+20*scale);
            context.arcTo(x+20*scale,y+20*scale,x+20*scale,y+10*scale,10*scale);
            context.lineCap="square";
            context.stroke();
            //Textfeld zeichnen
            context.strokeStyle="rgb(0,0,0)";
            context.fillStyle="rgb(0,0,0)";
            context.lineWidth=2*scale;
            context.beginPath();
            context.moveTo(x+90*scale,y+65*scale);
            context.lineTo(x+90*scale,y+100*scale);
            context.arcTo(x+80*scale,y+100*scale,x+80*scale,y+110*scale,10*scale);
            context.lineTo(x+20*scale,y+110*scale);
            context.arcTo(x+20*scale,y+100*scale,x+10*scale,y+100*scale,10*scale);
            context.lineTo(x+10*scale,y+65*scale);
            context.arcTo(x+20*scale,y+65*scale,x+20*scale,y+75*scale,10*scale);
            context.lineTo(x+80*scale,y+75*scale)
            context.arcTo(x+80*scale,y+65*scale,x+90*scale,y+65*scale,10*scale)
            context.lineCap="square";
            context.fill();
            context.stroke();
            //lvl zeichnen
            shift=0;
            for(var greystar=0;greystar<=4; greystar++){
                context.strokeStyle="rgb(100,100,100)";
                context.fillStyle="rgb(100,100,100)";
                context.beginPath();
                context.moveTo(shift+x+23.33*scale,y+112*scale);
                context.lineTo(shift+x+25.33*scale,y+118.66*scale);
                context.lineTo(shift+x+20*scale,y+114.53*scale);
                context.lineTo(shift+x+26.66*scale,y+114.53*scale);
                context.lineTo(shift+x+21.26*scale,y+118.66*scale);
                context.lineTo(shift+x+23.33*scale,y+112*scale);
                context.fill();
                shift+=13.5*scale;
            }
            shift=0;
            while(lvl>0){
                context.strokeStyle="yellow";
                context.fillStyle="yellow";
                context.beginPath();
                context.moveTo(shift+x+23.33*scale,y+112*scale);
                context.lineTo(shift+x+25.33*scale,y+118.66*scale);
                context.lineTo(shift+x+20*scale,y+114.53*scale);
                context.lineTo(shift+x+26.66*scale,y+114.53*scale);
                context.lineTo(shift+x+21.26*scale,y+118.66*scale);
                context.lineTo(shift+x+23.33*scale,y+112*scale);
                context.fill();
                shift+=13.5*scale;
                lvl--;
            }
            //Bild einbinden
            var chucknorris = new Image();
            chucknorris.onload = function() {
                context.drawImage(chucknorris,x+18*scale,y+18*scale,64*scale,49*scale);
            };
            chucknorris.src="pics/chucknorris.png";
            //Symbole einbinden
            //life
            var life = new Image();
            life.onload = function() {
                context.drawImage(life,x+87*scale,y+11*scale,7*scale,7*scale);
            };
            life.src="pics/heart_small.png";
            //magic
            var magic = new Image();
            magic.onload = function() {
                context.drawImage(magic,x+6*scale,y+11*scale,7*scale,7*scale);
            };
            magic.src="pics/magic_small.png";
            if(mage==true){
                //wand
                var wand = new Image();
                wand.onload = function() {
                    context.drawImage(wand,x+6*scale,y+102*scale,7*scale,7*scale);
                };
                wand.src="pics/wand_small.png";
            }
            else{
                //sword
                var sword = new Image();
                sword.onload = function() {
                    context.drawImage(sword,x+6*scale,y+102*scale,7*scale,7*scale);
                };
                sword.src="pics/sword_crossed_small.png";
            }
            //shield
            var shield = new Image();
            shield.onload = function() {
                context.drawImage(shield,x+85*scale,y+102*scale,7*scale,7*scale);
            };
            shield.src="pics/shield_small.png";
            //magic_shield
            var magic_shield = new Image();
            magic_shield.onload = function() {
                context.drawImage(magic_shield,x+91*scale,y+102*scale,7*scale,7*scale);
            };
            magic_shield.src="pics/magic_shield_small.png";
            //Text einfügen
            context.font = 'bold '+4*scale+'px Calibri';
            context.fillStyle = 'rgb(255,255,255)';
            context.fillText(headline,x+20*scale, y+80*scale);
            context.font = 'normal '+3*scale+'px Calibri';
            context.fillStyle = 'rgb(255,255,255)';
            wrapText(context, text, x+20*scale, y+85*scale, maxWidth, lineHeight, scale);
            //HP anzeigen
            context.font = 'bold 20pt Calibri';
            context.fillStyle = 'rgb(255,0,0)';
            var textmetric = context.measureText(HP);
            var textwidth = textmetric.width/2;
            context.fillText(HP,x-textwidth+90.25*scale, y+10*scale);
            //MP anzeigen
            context.fillStyle = 'rgb(0,0,255)';
            textmetric = context.measureText(MP);
            textwidth = textmetric.width/2;
            context.fillText(MP,x-textwidth+9.5*scale, y+10*scale);
            //AtckP anzeigen
            context.fillStyle = 'rgb(0,0,0)';
            textmetric = context.measureText(AtckP);
            textwidth = textmetric.width/2;
            context.fillText(AtckP,x-textwidth+9.5*scale, y+115*scale);
            //DefP und MDefP anzeigen
            context.fillStyle = 'rgb(0,0,0)';
            var DefAll = DefP+'/'+MDefP;
            textmetric = context.measureText(DefAll);
            textwidth = textmetric.width;
            context.fillText(DefAll,x-textwidth+98*scale, y+115*scale);
        };

我认为重要的部分在“//Bild einbinden”和“//Text einfügen”之间,但我不确定。

该函数稍后在测试代码中使用,如下所示:

RoundRect(0,0,4,5,false,'Chuck Norris','Wenn Chuck Norris spricht, hört Gott zu!!! Chuck Norris` Tränen können Krebs heilen. Nur schade dass er niemals weint!!! Chuck Norris geht manchmal Blut spenden. Nur nie sein eigenes. Und wenn doch, dann mit ner Knarre und nem Eimer!!!','100','0','120','20','60');
RoundRect(100,120,4,2,false,'Chuck Norris Vers 0.3','Wenn Chuck Norris spricht, hört Gott zu!!! Chuck Norris` Tränen können Krebs heilen. Nur schade dass er niemals weint!!! Chuck Norris geht manchmal Blut spenden. Nur nie sein eigenes. Und wenn doch, dann mit ner Knarre und nem Eimer!!!','50','100','60','10','30');

结果如下:

结果

我希望有人可以帮助我。提前谢谢您(<-希望 Google-Tranlator 就在这里-对我来说听起来不对...)。

编辑:我发现了问题的一部分,但我仍然需要一个解决方案:我试图在代码中设置一些“alert();”。结果很有趣:首先,第一张牌的背景被绘制出来。然后是第二张卡片的背景。之后,第一张牌的图像被抽出,然后是第二张牌的其他图像。因此,在绘制其他所有内容之后绘制的图像。所以问题是如何告诉 Canvas 立即绘制图像,或者至少在函数内绘制图像。

4

2 回答 2

1

You get the images drawn after everything because they are drawn in the callback of Image.onLoad().

This means that the function will first render the background of the first card, register a listener for your Image.onLoad events, then return, so that you can make the seconde call, which will render the background, and register another listener for the new Image.onLoad events. Then the first listener is triggered when the first image is loaded, so it will draw the picture, and a last the second listener will be triggered. Hence your result.

As for a way to resolve this issue, either you can load your images before drawing any card, and draw it directly in your function, avoiding to wait for the loading, or you hav to make your design Asynchronous-proof. You can get information about asynchronous programming here: http://www.html5rocks.com/en/tutorials/async/deferred/?redirect_from_locale=why

Edit: The second solution can help with the first one (which corresponds to the answer of enzhflep). The article recommands the use of jquery to deal with asynchronous events such as loading multiple images. But if you don't need jQuery, you can also code a small javascript object that can register images to be loaded, and trigger a listener when all images are loaded. This ressource seems to offer that specific object.

于 2012-10-06T09:48:33.993 回答
0

不是问题。你的英语很好。(你提到的翻译有点奇怪'提前谢谢你)

正如您似乎开始识别的那样,问题是由于加载图像所花费的时间..

每次抽卡时,都会加载其中的每个图像。一旦加载了每个图像,它的 onload 处理程序就会触发并将其绘制到画布上。现在,问题是有时当您绘制第二张卡片时,第一张卡片中的图像仍在加载。这意味着第二张卡片的部分内容在卡片 1 的图像加载之前已被绘制。当它们最终加载时,它们被绘制在 card2 的顶部。

您可以通过在页面的 init 函数中加载图像来解决此问题。

这是我使用的解决方案:

var canvas, context;

var chucknorris = new Image();
var life = new Image();
var magic = new Image();
var wand = new Image();
var sword = new Image();
var shield = new Image();
var magic_shield = new Image();

function myInit()
{
    chucknorris.src="img/girl.png"; //"pics/chucknorris.png";
    life.src="img/heartSmall.jpg"; //"pics/heart_small.png";
    magic.src="img/magicSmall.jpg"; //"pics/magic_small.png";
    wand.src="img/magicSmall.jpg"; //"pics/wand_small.png";
    sword.src="img/magicSmall.jpg"; //"pics/sword_crossed_small.png";
    shield.src="img/close.png"; //pics/shield_small.png";
    magic_shield.src="img/magicSmall.jpg"; //"pics/magic_shield_small.png";

    canvas = document.createElement('canvas');
    canvas.setAttribute('width', '400');
    canvas.setAttribute('height', '800');
    context = canvas.getContext('2d');
    document.body.appendChild(canvas);

    RoundRect(0,0,2,5,false,'Chuck Norris','Wenn Chuck Norris spricht, hört Gott zu!!! Chuck Norris` Tränen können Krebs heilen. Nur schade dass er niemals weint!!! Chuck Norris geht manchmal Blut spenden. Nur nie sein eigenes. Und wenn doch, dann mit ner Knarre und nem Eimer!!!','100','0','120','20','60');

    RoundRect(128,0,2,5,false,'Pussy Galore','She loves Austin Powers','100','0','120','20','60');
}



function RoundRect(x,y,scale,lvl,mage,headline,text,HP,MP,AtckP,DefP,MDefP)
{
    var mImages

    //Kartenumriss zeichnen
    context.globalCompositeOperation = "src-over";

    context.strokeStyle="rgb(0,0,0)";
    context.fillStyle="rgb(180,180,180)";
    context.lineWidth=2*scale;
    context.beginPath();
    context.moveTo(x+10*scale,y+0*scale);
    context.lineTo(x+90*scale,y+0*scale);
    context.arcTo(x+100*scale,y+0*scale,x+100*scale,y+10*scale,10*scale);
    context.lineTo(x+100*scale,y+110*scale);
    context.arcTo(x+100*scale,y+120*scale,x+90*scale,y+120*scale,10*scale);
    context.lineTo(x+10*scale,y+120*scale);
    context.arcTo(x+0*scale,y+120*scale,x+0*scale,y+110*scale,10*scale);
    context.lineTo(x+0*scale,y+10*scale);
    context.arcTo(x+0*scale,y+0*scale,x+10*scale,y+0*scale,10*scale);
    context.fill();
    context.stroke();
    //innerer Kartenumriss zeichnen
    context.strokeStyle="rgb(0,0,0)";
    context.lineWidth=2*scale;
    context.beginPath();
    context.moveTo(x+20*scale,y+10*scale)
    context.lineTo(x+80*scale,y+10*scale);
    context.arcTo(x+80*scale,y+20*scale,x+90*scale,y+20*scale,10*scale);
    context.lineTo(x+90*scale,y+100*scale);
    context.arcTo(x+80*scale,y+100*scale,x+80*scale,y+110*scale,10*scale);
    context.lineTo(x+20*scale,y+110*scale);
    context.arcTo(x+20*scale,y+100*scale,x+10*scale,y+100*scale,10*scale);
    context.lineTo(x+10*scale,y+20*scale);
    context.arcTo(x+20*scale,y+20*scale,x+20*scale,y+10*scale,10*scale);
    context.lineCap="square";
    context.stroke();
    //Textfeld zeichnen
    context.strokeStyle="rgb(0,0,0)";
    context.fillStyle="rgb(0,0,0)";
    context.lineWidth=2*scale;
    context.beginPath();
    context.moveTo(x+90*scale,y+65*scale);
    context.lineTo(x+90*scale,y+100*scale);
    context.arcTo(x+80*scale,y+100*scale,x+80*scale,y+110*scale,10*scale);
    context.lineTo(x+20*scale,y+110*scale);
    context.arcTo(x+20*scale,y+100*scale,x+10*scale,y+100*scale,10*scale);
    context.lineTo(x+10*scale,y+65*scale);
    context.arcTo(x+20*scale,y+65*scale,x+20*scale,y+75*scale,10*scale);
    context.lineTo(x+80*scale,y+75*scale)
    context.arcTo(x+80*scale,y+65*scale,x+90*scale,y+65*scale,10*scale)
    context.lineCap="square";
    context.fill();
    context.stroke();
    //lvl zeichnen
    shift=0;
    for(var greystar=0;greystar<=4; greystar++)
    {
        context.strokeStyle="rgb(100,100,100)";
        context.fillStyle="rgb(100,100,100)";
        context.beginPath();
        context.moveTo(shift+x+23.33*scale,y+112*scale);
        context.lineTo(shift+x+25.33*scale,y+118.66*scale);
        context.lineTo(shift+x+20*scale,y+114.53*scale);
        context.lineTo(shift+x+26.66*scale,y+114.53*scale);
        context.lineTo(shift+x+21.26*scale,y+118.66*scale);
        context.lineTo(shift+x+23.33*scale,y+112*scale);
        context.fill();
        shift+=13.5*scale;
    }
    shift=0;
    while(lvl>0)
    {
        context.strokeStyle="yellow";
        context.fillStyle="yellow";
        context.beginPath();
        context.moveTo(shift+x+23.33*scale,y+112*scale);
        context.lineTo(shift+x+25.33*scale,y+118.66*scale);
        context.lineTo(shift+x+20*scale,y+114.53*scale);
        context.lineTo(shift+x+26.66*scale,y+114.53*scale);
        context.lineTo(shift+x+21.26*scale,y+118.66*scale);
        context.lineTo(shift+x+23.33*scale,y+112*scale);
        context.fill();
        shift+=13.5*scale;
        lvl--;
    }
    //Bild einbinden
    context.drawImage(chucknorris,x+18*scale,y+18*scale,64*scale,49*scale);

    //Symbole einbinden
    //life
    context.drawImage(life,x+87*scale,y+11*scale,7*scale,7*scale);

    //magic
        context.drawImage(magic,x+6*scale,y+11*scale,7*scale,7*scale);
    if(mage==true)
    {
        context.drawImage(wand,x+6*scale,y+102*scale,7*scale,7*scale);
    }
    else{
            context.drawImage(sword,x+6*scale,y+102*scale,7*scale,7*scale);
    }
    //shield
        context.drawImage(shield,x+85*scale,y+102*scale,7*scale,7*scale);

        //magic_shield
//  magic_shield.onload = function() {
        context.drawImage(magic_shield,x+91*scale,y+102*scale,7*scale,7*scale);
//  };

    //Text einfügen
    context.font = 'bold '+4*scale+'px Calibri';
    context.fillStyle = 'rgb(255,255,255)';
    context.fillText(headline,x+20*scale, y+80*scale);
    context.font = 'normal '+3*scale+'px Calibri';
    context.fillStyle = 'rgb(255,255,255)';
    wrapText(context, text, x+20*scale, y+85*scale, maxWidth, lineHeight, scale);
    //HP anzeigen
    context.font = 'bold 20pt Calibri';
    context.fillStyle = 'rgb(255,0,0)';
    var textmetric = context.measureText(HP);
    var textwidth = textmetric.width/2;
    context.fillText(HP,x-textwidth+90.25*scale, y+10*scale);
    //MP anzeigen
    context.fillStyle = 'rgb(0,0,255)';
    textmetric = context.measureText(MP);
    textwidth = textmetric.width/2;
    context.fillText(MP,x-textwidth+9.5*scale, y+10*scale);
    //AtckP anzeigen
    context.fillStyle = 'rgb(0,0,0)';
    textmetric = context.measureText(AtckP);
    textwidth = textmetric.width/2;
    context.fillText(AtckP,x-textwidth+9.5*scale, y+115*scale);
    //DefP und MDefP anzeigen
    context.fillStyle = 'rgb(0,0,0)';
    var DefAll = DefP+'/'+MDefP;
    textmetric = context.measureText(DefAll);
    textwidth = textmetric.width;
    context.fillText(DefAll,x-textwidth+98*scale, y+115*scale);
};
于 2012-10-06T09:50:16.637 回答