0

私の質問は、HTML Canvas の関数を使用した描画についてです。Canvasで「トレーディングカード」を描いてゲームを作ってみました。そこで、さまざまなカードを引くために必要なすべての情報を取得する関数を作成することにしました。1 枚のカードの場合 - 問題ありません。しかし、最初のカードの上に別のカードを引こうとすると、最初のカードの画像が 2 番目のカードを通して見えてしまいます。

ソースコードは次のとおりです。

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();」を設定しようとしました。結果は興味深いものでした。まず、最初のカードの背景が描かれます。続いて2枚目のカードの背景。その後、最初のカードの画像が描かれ、次に 2 番目のカードから他の画像が描かれます。したがって、他のすべてが描画された後に描画される画像。したがって、問題は、キャンバスに画像をすぐに、または少なくとも関数内で描画するように指示する方法です。

4

2 に答える 2

1

Image.onLoad() のコールバックで描画されるため、すべての後に描画される画像を取得します。

これは、関数が最初に最初のカードの背景をレンダリングし、Image.onLoad イベントのリスナーを登録してから戻ることを意味します。これにより、背景をレンダリングする 2 番目の呼び出しを行い、新しいイベントに別のリスナーを登録できます。 Image.onLoad イベント。次に、最初の画像が読み込まれると最初のリスナーがトリガーされるため、画像が描画され、最後に2番目のリスナーがトリガーされます。したがって、あなたの結果。

この問題を解決する方法としては、カードを描画する前に画像をロードし、ロードを待たずに関数内で直接描画するか、デザインを非同期に対応させる必要があります。非同期プログラミングに関する情報は、http ://www.html5rocks.com/en/tutorials/async/deferred/?redirect_from_locale=why で入手できます。

編集: 2 番目の解決策は、最初の解決策 (enzhflep の回答に対応) に役立ちます。この記事では、jquery を使用して、複数の画像の読み込みなどの非同期イベントを処理することを推奨しています。ただし、jQuery が必要ない場合は、読み込む画像を登録し、すべての画像が読み込まれたときにリスナーをトリガーできる小さな JavaScript オブジェクトをコーディングすることもできます。このリソースは、その特定のオブジェクトを提供しているようです。

于 2012-10-06T09:48:33.993 に答える
0

問題はありません。あなたの英語は大丈夫です。(あなたが言及した翻訳は少し奇妙です '事前に感謝します)

あなたが特定し始めているように見えるように、問題は画像のロードにかかる時間によるものです..

カードを引くたびに、それぞれの画像をロードします。各画像が読み込まれると、onload ハンドラが起動し、キャンバスに描画されます。問題は、2 枚目のカードを引いたときに 1 枚目のカードの画像がまだ読み込まれている場合があることです。これは、カード 1 の画像が読み込まれる前に、2 番目のカードの一部が描画されたことを意味します。それらが最終的にロードされると、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 に答える