我的问题是在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”和“//Texteinfü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');
结果如下:
我希望有人可以帮助我。提前谢谢你(&lt; - 希望Google-Tranlator就在这里 - 对我来说听起来不错......)。
编辑: 我想出了问题的一部分,但我仍然需要一个解决方案: 我试着在代码中设置一些“alert();”。结果是有趣的:首先,绘制第一张牌的背景。然后是第二张牌的背景。之后,绘制第一张卡片的图像,然后从第二张卡片中绘制其他图像。所以在绘制其他所有内容后绘制的图像。 所以问题是如何告诉Canvas立即绘制图像,或者至少在函数内绘制图像。
答案 0 :(得分:1)
你得到的图像是在一切之后绘制的,因为它们是在Image.onLoad()的回调中绘制的。
这意味着该函数将首先渲染第一张卡片的背景,为您的Image.onLoad事件注册一个监听器,然后返回,这样您就可以进行seconde调用,这将渲染背景,并注册另一个监听器对于新的Image.onLoad事件。然后在加载第一个图像时触发第一个侦听器,因此它将绘制图片,最后一个第二个侦听器将被触发。因此你的结果。
至于解决此问题的方法,您可以在绘制任何卡之前加载图像,然后直接在您的函数中绘制它,避免等待加载,或者您可以使您的设计异步防护。您可以在此处获取有关异步编程的信息:http://www.html5rocks.com/en/tutorials/async/deferred/?redirect_from_locale=why
编辑:第二个解决方案可以帮助第一个解决方案(对应于enzhflep的答案)。本文建议使用jquery来处理异步事件,例如加载多个图像。但是如果你不需要jQuery,你也可以编写一个小的javascript对象,可以注册要加载的图像,并在加载所有图像时触发一个监听器。 This ressource似乎提供了这个特定的对象。
答案 1 :(得分: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);
};