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