在画布中旋转单个对象? [英] Rotate individual objects in canvas?

查看:98
本文介绍了在画布中旋转单个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

rotate()函数似乎会旋转整个绘图区域。有没有办法单独旋转路径?我希望旋转中心是对象,而不是绘图区域。

the rotate() function seems to rotate the whole drawing area. Is there a way to rotate paths individually? I want the center for the rotation to be the object, not the drawing area.

使用 save() restore()仍然使旋转考虑到整个绘图区域。

Using save() and restore() still makes rotate take into account the whole drawing area.

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.save();
context.fillStyle = 'red';
context.rotate(0.35);
context.fillRect(40,40, 100, 100);
context.restore();

context.save();
context.fillStyle = 'blue';
context.rotate(0.35);
context.fillRect(200, 40, 100, 100);
context.restore();

<canvas id="canvas" width="500" height="500"></canvas>

推荐答案

使用本地空间

而不是在您想要的位置绘制对象,而是在其本地空间中绘制自己原点周围的所有内容。原点位于(0,0)并且是对象旋转的位置。

Instead of drawing object at the position you want them draw everything around its own origin in its local space. The origin is at (0,0) and is the location that the object rotates around.

因此,如果你有一个用

function drawRect(){
    context.fillRect(200, 40, 100, 100);
}

更改它以便在其原点绘制

change it so that it is drawn at its origin

function drawRect(){
    context.fillRect(-50,-50 , 100, 100);
}

现在您可以轻松地将其绘制到任何您想要的地方

Now you can easily draw it wherevery you want

从setTransform函数开始,因为它清除任何现有的变换,并且是设置对象中心位置的便捷方式

Start with the setTransform function as that clears any existing tranforms and is a convenient way to set the location of the center of the object will be

ctx.setTransform(1,0,0,1,posX,posY); // clear transform and set center location 

如果要旋转它然后添加旋转

if you want to rotate it then add the rotation

ctx.rotate(ang);

并按比例缩放

ctx.scale(scale,scale);

如果你有两个不同的音阶,你应该在旋转前缩放。

if you have two different scales you should scale before the rotate.

现在只需调用绘制函数

drawRect();

它的中心位于posX,posY旋转并缩放。

and it is drawn with its center at posX,posY rotated and scaled.

您可以将它全部组合成具有x,y位置,宽度和高度,比例和旋转的函数。您可以在setTransform中包含比例

You can combine it all into a function that has the x,y position, the width and the height, scale and rotation. You can include the scale in the setTransform

function drawRect(x,y,w,h,scale,rotation){
   ctx.setTransform(scale,0,0,scale,x,y);
   ctx.rotate(rotation);
   ctx.strokeRect(-w/2,-h/2,w,h);
}

它也适用于作为精灵的图像,我将包含一个alpha

It also applies to an image as a sprite, and I will include a alpha

function drawImage(img,x,y,w,h,scale,rotation,alpha){
   ctx.globalAlpha = alpha;
   ctx.setTransform(scale,0,0,scale,x,y);
   ctx.rotate(rotation);
   ctx.drawImage(img,-img.width/2,-img.height/2,img.width,img.height);
}

在6岁的笔记本电脑上,可以每1个在Firefox上绘制2000个精灵每秒60秒,每个都旋转,缩放,定位,并带有alpha淡入淡出。

On a 6 year old laptop that can draw 2000 sprites on firefox every 1/60th of a second, each rotated, scaled, positioned, and with a alpha fade.

无需翻转前后翻译。只需保留您在其周围绘制的所有对象,并通过转换移动该原点。

No need to mess about with translating back and forward. Just keep all the objects you draw around there own origins and move that origin via the transform.

更新
丢失演示所以这里是为了展示如何在实践中做到这一点。

Update Lost the demo so here it is to show how to do it in practice.

只需绘制大量旋转,缩放的翻译,带alpha的矩形。

Just draws a lot of rotated, scaled translated, alphaed rectangles.

通过使用setTransform,您可以避免保存和恢复来节省大量时间

By using setTransform you save a lot of time by avoiding save and restore

// create canvas and add resize 
var canvas,ctx;
function createCanvas(){
    canvas = document.createElement("canvas"); 
    canvas.style.position = "absolute";
    canvas.style.left     = "0px";
    canvas.style.top      = "0px";
    canvas.style.zIndex   = 1000;
    document.body.appendChild(canvas); 
}
function resizeCanvas(){
    if(canvas === undefined){
        createCanvas();
    }
    canvas.width          = window.innerWidth;
    canvas.height         = window.innerHeight; 
    ctx            = canvas.getContext("2d"); 
}
resizeCanvas();
window.addEventListener("resize",resizeCanvas);


// simple function to draw a rectangle
var drawRect = function(x,y,w,h,scale,rot,alpha,col){
  ctx.setTransform(scale,0,0,scale,x,y);
  ctx.rotate(rot);
  ctx.globalAlpha = alpha;
  ctx.strokeStyle = col;
  ctx.strokeRect(-w/2,-h/2, w, h);

}

// create some rectangles in unit scale so that they can be scaled to fit
// what ever screen size this is in
var rects = [];
for(var i = 0; i < 200; i ++){
  rects[i] = {
    x : Math.random(),
    y : Math.random(),
    w : Math.random() * 0.1,
    h : Math.random() * 0.1,
    scale : 1, 
    rotate : 0,
    dr : (Math.random() - 0.5)*0.1, // rotation rate
    ds : Math.random()*0.01,   // scale vary rate
    da : Math.random()*0.01,   // alpha vary rate
    col : "hsl("+Math.floor(Math.random()*360)+",100%,50%)",
  };
}

// draw everything once a frame
function update(time){
  var w,h;
  w = canvas.width;  // get canvas size incase there has been a resize
  h = canvas.height;
  ctx.setTransform(1,0,0,1,0,0); // reset transform
  ctx.clearRect(0,0,w,h);  // clear the canvas
  
  // update and draw each rect
  for(var i = 0; i < rects.length; i ++){
    var rec = rects[i];
    rec.rotate += rec.dr;
    drawRect(rec.x * w, rec.y * h, rec.w * w,rec.h * h,rec.scale + Math.sin(time * rec.ds) * 0.4,rec.rotate,Math.sin(time * rec.da) *0.5 + 0.5,rec.col);
  }
  
  requestAnimationFrame(update); // do it all again
}
requestAnimationFrame(update);

这篇关于在画布中旋转单个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆