javascript - 旋转 Canvas 中的单个对象?

标签 javascript canvas rotation

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

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

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),是对象旋转的位置。

所以如果你有一个用来绘制的矩形

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

改变它,让它在原点绘制

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

现在你可以随心所欲地绘制它了

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

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

如果你想旋转它然后添加旋转

ctx.rotate(ang);

并缩放

ctx.scale(scale,scale);

如果您有两个不同的缩放比例,您应该在旋转之前缩放。

现在调用draw函数就可以了

drawRect();

绘制时以 posX,posY 为中心旋转缩放。

您可以将它们组合成一个具有 x,y 位置、宽度和高度、比例和旋转的函数。您可以在 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);
}

它也适用于作为 Sprite 的图像,我将包含一个 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/60 秒可以在 Firefox 上绘制 2000 个 Sprite ,每个 Sprite 都经过旋转、缩放、定位,并带有 alpha 淡入淡出。

无需为来回翻译而烦恼。只需让您在周围绘制的所有对象都有自己的原点,并通过变换移动该原点即可。

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

只是绘制了很多旋转的、缩放的、翻译的、alphaed 的矩形。

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

// 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);

关于javascript - 旋转 Canvas 中的单个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36946204/

相关文章:

canvas - Flutter:如何在 Canvas 上绘制图标?

javascript - 在一定范围内使用 paper.js 进行颜色转换

javascript - 如何在 javaScript 中使用特定键对对象进行分组

javascript - Javascript 中的动态 setInterval

javascript - 如何在 Canvas 内绘制文本框

android - 如何旋转 Genymotion 模拟器

c++ - OpenGL - 为 glRotate() 找到旋转 vector

ios - 将 UIView 旋转 360 度或更多

javascript - 使用javascript在textarea中显示文本

javascript - 如何将点击处理程序添加到 gwt 可视化图表的 x-label 元素