2016-04-29 93 views
1

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>

回答

2

使用本地空间

相反的位置描绘对象,你希望他们周围画了自己的一切都起源在其本地空间。原点位于(0,0)处,并且是对象旋转的位置。

所以,如果您有与

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

改变它绘制,以便它在它的起源绘制一个矩形

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

现在你可以很容易地画出它wherevery你想

以setTransform函数开始,因为它可以清除任何现有的变形,并且是设置对象中心位置的便捷方法将是

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

如果你想旋转,然后将其与

ctx.scale(scale,scale); 

添加旋转

ctx.rotate(ang); 

和规模,如果你有你的旋转前,应扩大两个不同的尺度。

现在只需调用绘制函数

drawRect(); 

,并绘制其在POSX中心,波西旋转和缩放。

你可以把它全部合并成一个具有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); 
} 

它也适用于图像作为一个精灵,我将包括阿尔法

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岁的笔记本电脑,可以借鉴2000个精灵firefox每1/60秒,每个旋转,缩放,定位,并与阿尔法淡入淡出。

没有必要混淆翻译回来和前进。只需保留所有绘制的对象都有自己的原点并通过变换移动原点。

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

只画了很多旋转的,缩放翻译的字母矩形。

使用的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);

0

在画布上的所有变革都为整个绘制区域。如果你想围绕一个点旋转,你将不得不将这个点翻译成原点,做你的旋转并翻译回来。像this就是你想要的东西。

+0

但第二次旋转仍会影响第一个对象吗?那不是我想要的。我想每个旋转只影响之前绘制的对象 – katie

+0

转换适用于后面发生的事情。所以当你在调用rotate之后调用fillRect的时候,就是前面的rotate应用了。如果要为第二个对象旋转不同的量,请在调用它之前使用不同的旋转值。 – CrazyCasta

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>