使用本地空间
而不是在您希望他们在其本地空间中围绕其自己的原点绘制所有内容的位置绘制对象。原点位于 (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 个精灵,每个精灵都经过旋转、缩放、定位,并带有 alpha 渐变。
无需纠结于前后翻译。只需保留您在其中绘制的所有对象都有自己的原点并通过变换移动该原点。
更新
丢了演示,所以这里是展示如何在实践中做到这一点。
只绘制大量旋转、缩放、平移、带字母的矩形。
使用 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);