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>
最佳答案
使用本地空间
不是在您希望的位置绘制对象,而是在其局部空间中围绕其自身原点绘制所有内容。原点位于 (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);
如果您有两个不同的缩放比例,您应该在旋转之前缩放。
现在调用draw函数就可以了
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);
}
它也适用于作为 Sprite 的图像,我将包含一个 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 个 Sprite ,每个 Sprite 都经过旋转、缩放、定位,并带有 alpha 淡入淡出。
无需为来回翻译而烦恼。只需让您在周围绘制的所有对象都有自己的原点,并通过变换移动该原点即可。
更新 失去了演示,所以这里是展示如何在实践中做到这一点。
只是绘制了很多旋转的、缩放的、翻译的、alphaed 的矩形。
通过使用 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);
关于javascript - 旋转 Canvas 中的单个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36946204/