在画布中旋转单个对象?

时间:2016-04-29 19:35:10

标签: 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>

3 个答案:

答案 0 :(得分:2)

使用本地空间

不是在您想要的位置绘制对象,而是在其本地空间中围绕其自己的原点绘制所有内容。原点位于(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);

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

现在只需调用绘制函数

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

它也适用于作为精灵的图像,我将包含一个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个精灵,每个旋转,缩放,定位,并且有淡入淡出。

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

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

只需绘制大量旋转,缩放的平移字母矩形。

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

&#13;
&#13;
// 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);
&#13;
&#13;
&#13;

答案 1 :(得分:0)

画布中的所有变换都适用于整个绘图区域。如果您想围绕一个点旋转,您必须将该点转换为原点,请进行旋转并将其转换回来。像this这样的东西就是你想要的。

答案 2 :(得分:0)

使用旋转功能旋转其中心周围的所有形状点。

<!DOCTYPE html>
<html>
<head>
    <style>
        body
        {
            margin: 0px;
            padding: 0px;
            overflow: hidden;
        }
        canvas
        {
            position: absolute;
        }
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    var canvas;
    var context;
    canvas = document.getElementById("canvas");
    context = canvas.getContext("2d");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    var degreesToRadians = function(degrees)
    {
        return degrees*Math.PI/180;
    }
    var rotate = function(x, y, cx, cy, degrees)
    {
        var radians = degreesToRadians(degrees);
        var cos = Math.cos(radians);
        var sin = Math.sin(radians);
        var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx;
        var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
        return new Vector2(nx, ny);
    }
    var Vector2 = function(x, y)
    {
        return {x:x,y:y};
    }
    var Shape = function(points, color)
    {
        this.color = color;
        this.points = points;
    };
    Shape.prototype.rotate = function(degrees)
    {
        var center = this.getCenter();
        for (var i = 0; i < this.points.length; i++)
        {
            this.points[i] = rotate(this.points[i].x,this.points[i].y,center.x,center.y,degrees);
        }
        context.beginPath();
        context.arc(center.x,center.y,35,0,Math.PI*2);
        context.closePath();
        context.stroke();
    }
    Shape.prototype.draw = function()
    {
        context.fillStyle = this.color;
        context.strokeStyle = "#000000";
        context.beginPath();
        context.moveTo(this.points[0].x, this.points[0].y);
        for (var i = 0; i < this.points.length; i++)
        {
            context.lineTo(this.points[i].x, this.points[i].y);
            //context.fillText(i+1, this.points[i].x, this.points[i].y);
        }
        context.closePath();
        context.fill();
        context.stroke();
    }
    Shape.prototype.getCenter = function()
    {
        var center = {x:0,y:0};
        for (var i = 0; i < this.points.length; i++)
        {
            center.x += this.points[i].x;
            center.y += this.points[i].y;
        }
        center.x /= this.points.length;
        center.y /= this.points.length;
        return center;
    }
    Shape.prototype.translate = function(x, y)
    {
        for (var i = 0; i < this.points.length; i++)
        {
            this.points[i].x += x;
            this.points[i].y += y;
        }
    }
    var Rect = function(x,y,w,h,c)
    {
        this.color = c;
        this.points = [Vector2(x,y),Vector2(x+w,y),Vector2(x+w,y+h),Vector2(x,y+h)];
    }
    Rect.prototype = Shape.prototype;
    var r = new Rect(50, 50, 200, 100, "#ff0000");
    r.draw();
    r.translate(300,0);
    r.rotate(30);
    r.draw();

</script>
</body>
</html>