繁体   English   中英

如何在HTML5画布中绘制和旋转图像以及文本

[英]How to draw and rotate image along with text in HTML5 canvas

我在画布上绘制和旋转图像时遇到问题。 基本上,我的方法是创造命运之轮,该命运之轮允许根据阵列形式的奖品进行自定义。 该数组中的数据根据​​索引数组成了转轮内部的片段。

数据非常简单。 就像这样一个简单的JSON对象

var prizes = [
{product:"Axe FX", img: "https://mdn.mozillademos.org/files/5395/backdrop.png"},
{product:"Musicman JPX", img: "https://mdn.mozillademos.org/files/5395/backdrop.png"},
{product:"Ibanez JEM777V", img: "https://mdn.mozillademos.org/files/5395/backdrop.png"}
];

该数据用于在车轮内部创建线段。 因此,我想放置当前正在工作的文字,对我来说就像是一种魅力。

拉动轮子时,我分为两个主要功能。 一个绘制车轮,另一个绘制车轮内的线段。

var drawPartial = function(key, lastAngle, angle) {
var value = prizes[key].product;

ctx.save();
ctx.beginPath();
ctx.lineWidth = 6;
ctx.fillStyle = segColors[key];
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, size, lastAngle, angle);
ctx.lineTo(centerX, centerY);
ctx.closePath();
ctx.stroke();
ctx.fill();

ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((lastAngle+angle) / 2);
ctx.fillStyle = "#000";
ctx.fillText(value.substr(0,20), size / 2 + 20, 0);
ctx.restore();

ctx.restore();
}

var draw = function() {
var len = prizes.length;
var currentAngle = outCurrentAngle;
var lastAngle = currentAngle;

ctx.strokeStyle = '#000000';
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.font = "1.4em Arial";

for(var i = 1; i <= len; i++) {
    var angle = (Math.PI*2) * (i/len) + currentAngle;
    drawPartial(i-1, lastAngle, angle);
    lastAngle = angle;
}

ctx.beginPath();
ctx.lineWidth = 2;
ctx.fillStyle = "#fff";
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, size/7, 0, Math.PI*2);
ctx.closePath();
// ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.lineWidth = 10;
ctx.arc(centerX, centerY, size, 0, Math.PI*2);
ctx.closePath();
// ctx.stroke();
}

使用上面的代码,我只需要简单地调用draw()函数,即可相应地创建wheel和所有线段。 但是,我想在每个片段中绘制图像,但是我不知道该图像是否起作用。 这是drawPartial()的修改,用于与文本一起呈现图像

var drawPartial = function(key, lastAngle, angle) {
var value = prizes[key].product;

var img = new Image();
img.src = prizes[key].img;
img.onload = function() { 

    ctx.save();
    ctx.drawImage(img,centerX,centerY);

    ctx.save();
    ctx.translate(centerX,centerY);
    ctx.rotate((lastAngle+angle) / 2);
    ctx.drawImage(img,centerX,centerY);

    ctx.restore();
    ctx.restore();


}

ctx.save();
ctx.beginPath();
ctx.lineWidth = 6;
ctx.fillStyle = segColors[key];
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, size, lastAngle, angle);
ctx.lineTo(centerX, centerY);
ctx.closePath();
ctx.stroke();
ctx.fill();

ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((lastAngle+angle) / 2);
ctx.fillStyle = "#000";
ctx.fillText(value.substr(0,20), size / 2 + 20, 0);
ctx.restore();

ctx.restore();
}

可以看到,我根据基于奖品的对象添加了图像及其src,应该在主draw()函数调用的每次迭代中调用该图像及其src,但它永远不会在任何段中呈现任何图像。

我想要的是。 在drawPartial()的每次迭代中,我希望将图像与文本一起放置在段中,并根据角度旋转。

请帮忙...

问题

img.onload函数中,您正在“双重翻译”您的centerX和centerY。

ctx.translate(centerX,centerY)将画布的[0,0]原点移动到[centerX,centerY]。

因此,当您ctx.drawImage(img,centerX,centerY)绘制图像时,您实际上是两次搬家。

结果,您的图像实际上是在[ centerX*2, centerY*2 ]处绘制的。

另一个想法:预加载图像

最好预先加载所有图像。 这样,如果图像无法加载,则可以在开始绘制轮子之前采取修复措施。

以下是如何预加载所有图像的方法,以便在需要将其绘制到Wheel上时可以使用它们:

 // your incoming JSON var prizesJSON='[{"product":"Axe FX","img":"https://mdn.mozillademos.org/files/5395/backdrop.png"},{"product":"Musicman JPX","img":"https://mdn.mozillademos.org/files/5395/backdrop.png"},{"product":"Ibanez JEM777V","img":"https://mdn.mozillademos.org/files/5395/backdrop.png"}]'; // the JSON converted to a JS array of objects var prizes=JSON.parse(prizesJSON); // preload all images var imageURLs=[]; var imgs=[]; var imagesOK=0; // add prize images into the image preloader for(var i=0;i<prizes.length;i++){ imageURLs.push(prizes[i].img); } startLoadingAllImages(imagesAreNowLoaded); // function startLoadingAllImages(callback){ for (var i=0; i<imageURLs.length; i++) { var img = new Image(); imgs.push(img); img.onload = function(){ imagesOK++; if (imagesOK>=imageURLs.length ) { callback(); } }; img.onerror=function(){alert("image load failed");} img.src = imageURLs[i]; } } // function imagesAreNowLoaded(){ // add the img objects to your prizes array objects for(var i=0;i<prizes.length;i++){ prizes[i].imageObject=imgs[i]; // just testing (add the img to the DOM) document.body.appendChild(imgs[i]); } // All images are fully loaded // So draw your wheel now! } 
 body{ background-color: ivory; } 
 <h4>Testing: (1) Preload all images, (2) Add imgs to DOM</h4> 

我有这个躺在...

我看到您已经有了绘制Wheel的代码,但是我的代码档案中已有此代码,因此在此提供此代码是为了防止对您有所用。

这是一个如何绘制“命运之轮”的示例,每个刀片都包含奖品图像和文字。 使用的技术包括:

  • context.translate将旋转点设置为车轮的中心。
  • context.rotate将每个刀片旋转到所需角度。
  • context.textAligncontext.textBaseline绘制居中文本。
  • context.globalAlpha可以淡化每个刀片的颜色,因此黑色文本具有良好的对比度。

在此处输入图片说明

 var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var cw=canvas.width; var ch=canvas.height; var PI=Math.PI; var PI2=PI*2; var bladeCount=10; var sweep=PI2/bladeCount; var cx=cw/2; var cy=ch/2; var radius=130; var img=new Image(); img.onload=start; img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png"; function start(){ for(var i=0;i<bladeCount;i++){ drawBlade(img,'House'+i,cx,cy,radius,sweep*i,sweep); } } function drawBlade(img,text,cx,cy,radius,angle,arcsweep){ // save the context state ctx.save(); // rotate the canvas to this blade's angle ctx.translate(cx,cy); ctx.rotate(angle); // draw the blade wedge ctx.lineWidth=1.5; ctx.beginPath(); ctx.moveTo(0,0); ctx.arc(0,0,radius,0,arcsweep); ctx.closePath(); ctx.stroke(); // fill the blade, but keep the color light // so the black text has good contrast ctx.fillStyle='white'; ctx.fill(); ctx.fillStyle=randomColor(); ctx.globalAlpha=0.30; ctx.fill(); ctx.globalAlpha=1.00; // draw the text ctx.rotate(PI/2+sweep/2); ctx.textAlign='center'; ctx.textBaseline='middle'; ctx.fillStyle='black'; ctx.fillText(text,0,-radius+50); // draw the img // (resize to 32x32 so be sure orig img is square) ctx.drawImage(img,-16,-radius+10,32,32); // restore the context to its original state ctx.restore(); } function randomColor(){ return('#'+Math.floor(Math.random()*16777215).toString(16)); } 
 body{ background-color: ivory; } #canvas{border:1px solid red; margin:0 auto; } 
 <canvas id="canvas" width=300 height=300></canvas> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM