我在 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()函数,轮子和所有段就会相应地创建。但是,我想在每个部分绘制图像,但我不知道如何使其工作。这是对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() 函数调用的每次迭代中调用,但它永远不会在任何片段中渲染任何图像。
我想要的是。在drawPartial()的每次迭代中,我希望图像与文本一起放置在片段中,并根据 Angular 旋转。
请帮忙...
最佳答案
问题
在您的 img.onload
函数中,您正在“双重翻译”您的 centerX 和 centerY。
ctx.translate(centerX,centerY)
会将 Canvas 的 [0,0] 原点移动到 [centerX,centerY]。
因此,当您ctx.drawImage(img,centerX,centerY)
绘制图像时,您实际上是在双重移动。
因此,您的图像实际上是在 [ centerX*2, centerY*2 ]
处绘制的。
附加想法:预加载图像
最好预加载所有图像。这样,如果图像加载失败,您可以在开始绘制轮子之前采取修复操作。
以下是如何预加载所有图像,以便在您需要将它们绘制到轮子上时可用:
// 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>
我有这个...
我看到您已经有了绘制轮子的代码,但我的代码存档中有此代码,因此我在这里提供它,以防万一它对您有用。
这里是如何绘制“命运之轮”的示例,每个叶片都包含奖品图像和文本。使用的技术包括:
context.translate
将旋转点设置为滚轮中心。context.rotate
将每个 Blade 旋转到所需的 Angular 。context.textAlign
和context.textBaseline
绘制居中文本。context.globalAlpha
淡化每个 Blade 的颜色,使黑色文本具有良好的对比度。
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>
关于javascript - 如何在 HTML5 Canvas 中随文本一起绘制和旋转图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32173955/