2016-04-29 19 views
1

Die rotate() Funktion scheint den gesamten Zeichenbereich zu drehen. Gibt es eine Möglichkeit, Pfade einzeln zu rotieren? Ich möchte, dass das Rotationszentrum das Objekt und nicht der Zeichenbereich ist.Einzelne Objekte in Canvas drehen?

Mit save() und restore() wird immer noch die gesamte Zeichnungsfläche berücksichtigt.

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>

Antwort

2

Verwenden lokalen Raum

Statt Zeichenobjekt an der Position wollen sie alles um die eigene Herkunft in seinem lokalen Raum ziehen. Der Ursprung liegt bei (0,0) und ist der Ort, um den sich das Objekt dreht.

Also, wenn Sie ein Rechteck, das Sie mit

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

ändern, so dass sie an ihrem Ursprung gezogen wird

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

Jetzt können Sie leicht ziehen wherevery Sie

Beginnen Sie mit der Funktion setTransform, die vorhandene Transformationen löscht und die Position des Mittelpunkts des Objekts auf bequeme Weise

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

wenn Sie wollen, drehen Sie es um die Drehung dann fügen

ctx.rotate(ang); 

und Skala mit

ctx.scale(scale,scale); 

wenn Sie zwei verschiedene Skalen haben Sie vor dem Drehen Skalieren sollte.

Nun rufen Sie einfach die Zeichenfunktion

drawRect(); 

und es mit seinem Zentrum bei posX gezogen wird, posY gedreht und skaliert werden.

Sie können alles zu einer Funktion kombinieren, die die x, y-Position, die Breite und die Höhe, Skalierung und Drehung hat. Sie können den Maßstab in der setTransform umfassen

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

Es gilt auch für ein Bild, wie ein Sprite, und ich will ein 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); 
} 

Auf einem 6 Jahre alten Laptop enthalten, die auf 2000 Sprites zeichnen firefox alle 1/60s einer Sekunde, jeweils gedreht, skaliert, positioniert und mit einem Alpha-Fade.

Kein unnötiges Hin und Her mit dem Übersetzen. Behalte einfach alle Objekte, die du zeichnest, um eigene Ursprünge und verschiebe diesen Ursprung über die Transformation.

Update Verloren die Demo so hier ist es zu zeigen, wie es in der Praxis zu tun.

Zeichnet nur viele gedrehte, skalierte übersetzte, alphabetische Rechtecke.

von setTransform verwenden Sie eine Menge Zeit sparen, indem

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

Alle Transformationen in Leinwand sind für die gesamte Zeichenfläche. Wenn Sie sich um einen Punkt drehen wollen, müssen Sie diesen Punkt in den Ursprung übersetzen, Ihre Drehung ausführen und zurückübersetzen. Etwas wie this ist was du willst.

+0

aber die zweite drehen wird immer noch das erste Objekt beeinflussen? das ist nicht was ich dann will. Ich möchte jede drehen, um nur das Objekt zu beeinflussen, das vor gezeichnet wurde – katie

+0

Transformationen gelten für das, was nach ihnen passiert. Wenn Sie also fillRect nach dem Aufruf von rotate aufrufen, gilt die vorangegangene Drehung. Wenn Sie für das zweite Objekt um einen anderen Betrag drehen möchten, verwenden Sie einfach einen anderen Rotationswert, bevor Sie ihn aufrufen. – CrazyCasta

0

Verwenden einer Drehfunktion alle die Form der Punkte um seinen Mittelpunkt zu drehen, speichern und wiederherstellen zu vermeiden.

<!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> 
Verwandte Themen