[英]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.textAlign
和context.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.