【问题标题】:How to draw and rotate image along with text in HTML5 canvas如何在 HTML5 画布中绘制和旋转图像以及文本
【发布时间】:2015-11-17 09:12:58
【问题描述】:

我在画布上绘制和旋转图像时遇到问题。基本上,我的方法是创建幸运之轮,它允许基于数组形式的奖品进行定制。该数组中的数据根据​​索引的数量组成轮子内的段。

数据很简单。它只是一个像这样的简单 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() 的每次迭代中,我希望图像与文本一起放置在段中并根据角度旋转。

请帮忙...

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    问题

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

    ctx.translate(centerX,centerY) 会将画布的 [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; }
    &lt;h4&gt;Testing: (1) Preload all images, (2) Add imgs to DOM&lt;/h4&gt;

    我把这个放在身边……

    我看到您已经有了绘制车轮的代码,但我的代码存档中有此代码,所以我在这里提供它以防万一它对您有用。

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

    • 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; }
    &lt;canvas id="canvas" width=300 height=300&gt;&lt;/canvas&gt;

    【讨论】:

      猜你喜欢
      • 2011-03-11
      • 2016-04-12
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      相关资源
      最近更新 更多