我怎样才能在不迷失方向的情况下移动旋转的 canvas 图像?
How can i move rotated canvas image whitout disorientation?
我已将图像加载到 canvas。旋转后,我无法(拖动)正确移动图像。实际上,它会移动,但它会根据图像的坐标平面移动。因此,将旋转 90 度的图像向右移动,会向下移动,而不是像预期的那样向右移动。解决这个问题的好方法是什么?
这是我的绘制函数:
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount );
var im_height = parseInt( imageObj.height + resizeAmount );
var rotationAmount = rotationVal - prevRotation;
prevRotation = rotationVal;
context.clearRect( 0, 0, canvas.width, canvas.height );
context.translate( canvas.width/2, canvas.height/2 );
context.rotate( rotationAmount * Math.PI / 180 );
context.translate( -canvas.width/2, -canvas.height/2 );
context.drawImage( imageObj, moveXAmount, moveYAmount, im_width, im_height );
}
这里是 jsdiddle 你可以模拟一下看看我的意思。
PS: 您可以使用左侧的滑块旋转图像。底部滑块用于缩放。如果图片在第一次加载时没有出现,请重新运行 fiddle。
绘制后重置变换。鼠标事件在应用于 canvas 上下文时也会发生转换,因此仅在绘图时使用转换可以解决此问题。但是,这也要求代码使用绝对值,例如:
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount, 10 );
var im_height = parseInt( imageObj.height + resizeAmount, 10 );
var rotationAmount = rotationVal; // disabled: - prevRotation;
context.clearRect( 0, 0, canvas.width, canvas.height );
// move to origin first
context.translate( moveXAmount, moveYAmount );
// rotate
context.rotate( rotationAmount * Math.PI / 180 );
// change to translate back based on image size
// (remember to compensate for scale, not shown here)
context.translate( -imageObj.width/2, -imageObj.height/2 );
context.drawImage( imageObj, 0, 0, im_width, im_height );
// reset transforms (identity matrix)
context.setTransform(1,0,0,1,0,0);
}
您可能需要使用逆矩阵。这是稍后我们可以根据当前变换矩阵取出 SVGMatrix 时可用的东西,但目前还没有广泛使用。否则,逆矩阵将应用于鼠标 x/y 位置,顾名思义,逆向主变换的效果。
可选择使用自定义变换矩阵解决方案来跟踪变换(我会邀请您查看我自己的方法here,它是免费的)。
PS:还修复了图像加载问题(参见 fiddle)。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
var x = 250;
var y = 500;
var width = 100;
var height = 100
var cx = x + 0.5 * width; // x of shape center
var cy = y + 0.5 * height; // y of shape center
class Meteor {
constuctor(degrees){
this.degrees = degrees;
//this.y = 0;
}
draw(d){
//this.y = y++
ctx.save();
ctx.translate(x,d)
ctx.rotate( (Math.PI / 180) * d); //rotate 25 degrees.
ctx.translate(-cx, -cy); //translate center
ctx.fillStyle = "#0000ff";
ctx.fillRect(x, y, width, height);
ctx.restore();
//ctx.setTransform(1, 0, 0, 1, 0, 0);
}
}
let m = new Meteor(90)
d = 0;
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height)
// Save the default state
d++;
m.draw(d)
// Restore the default state
ctx.fillRect(250, 40, 10, 10); //spaceship
ctx.fillRect(150, d, 100, 100);
window.requestAnimationFrame(animate)
}
animate()
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount, 10 );
var im_height = parseInt( imageObj.height + resizeAmount, 10 );
var rotationAmount = rotationVal; // disabled: - prevRotation;
context.clearRect( 0, 0, canvas.width, canvas.height );
// move to origin first
context.translate( moveXAmount, moveYAmount );
// rotate
context.rotate( rotationAmount * Math.PI / 180 );
// change to translate back based on image size
// (remember to compensate for scale, not shown here)
context.translate( -imageObj.width/2, -imageObj.height/2 );
context.drawImage( imageObj, 0, 0, im_width, im_height );
// reset transforms (identity matrix)
context.setTransform(1,0,0,1,0,0);
}
我已将图像加载到 canvas。旋转后,我无法(拖动)正确移动图像。实际上,它会移动,但它会根据图像的坐标平面移动。因此,将旋转 90 度的图像向右移动,会向下移动,而不是像预期的那样向右移动。解决这个问题的好方法是什么?
这是我的绘制函数:
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount );
var im_height = parseInt( imageObj.height + resizeAmount );
var rotationAmount = rotationVal - prevRotation;
prevRotation = rotationVal;
context.clearRect( 0, 0, canvas.width, canvas.height );
context.translate( canvas.width/2, canvas.height/2 );
context.rotate( rotationAmount * Math.PI / 180 );
context.translate( -canvas.width/2, -canvas.height/2 );
context.drawImage( imageObj, moveXAmount, moveYAmount, im_width, im_height );
}
这里是 jsdiddle 你可以模拟一下看看我的意思。
PS: 您可以使用左侧的滑块旋转图像。底部滑块用于缩放。如果图片在第一次加载时没有出现,请重新运行 fiddle。
绘制后重置变换。鼠标事件在应用于 canvas 上下文时也会发生转换,因此仅在绘图时使用转换可以解决此问题。但是,这也要求代码使用绝对值,例如:
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount, 10 );
var im_height = parseInt( imageObj.height + resizeAmount, 10 );
var rotationAmount = rotationVal; // disabled: - prevRotation;
context.clearRect( 0, 0, canvas.width, canvas.height );
// move to origin first
context.translate( moveXAmount, moveYAmount );
// rotate
context.rotate( rotationAmount * Math.PI / 180 );
// change to translate back based on image size
// (remember to compensate for scale, not shown here)
context.translate( -imageObj.width/2, -imageObj.height/2 );
context.drawImage( imageObj, 0, 0, im_width, im_height );
// reset transforms (identity matrix)
context.setTransform(1,0,0,1,0,0);
}
您可能需要使用逆矩阵。这是稍后我们可以根据当前变换矩阵取出 SVGMatrix 时可用的东西,但目前还没有广泛使用。否则,逆矩阵将应用于鼠标 x/y 位置,顾名思义,逆向主变换的效果。
可选择使用自定义变换矩阵解决方案来跟踪变换(我会邀请您查看我自己的方法here,它是免费的)。
PS:还修复了图像加载问题(参见 fiddle)。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
var x = 250;
var y = 500;
var width = 100;
var height = 100
var cx = x + 0.5 * width; // x of shape center
var cy = y + 0.5 * height; // y of shape center
class Meteor {
constuctor(degrees){
this.degrees = degrees;
//this.y = 0;
}
draw(d){
//this.y = y++
ctx.save();
ctx.translate(x,d)
ctx.rotate( (Math.PI / 180) * d); //rotate 25 degrees.
ctx.translate(-cx, -cy); //translate center
ctx.fillStyle = "#0000ff";
ctx.fillRect(x, y, width, height);
ctx.restore();
//ctx.setTransform(1, 0, 0, 1, 0, 0);
}
}
let m = new Meteor(90)
d = 0;
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height)
// Save the default state
d++;
m.draw(d)
// Restore the default state
ctx.fillRect(250, 40, 10, 10); //spaceship
ctx.fillRect(150, d, 100, 100);
window.requestAnimationFrame(animate)
}
animate()
function draw(){
var im_width = parseInt( imageObj.width + resizeAmount, 10 );
var im_height = parseInt( imageObj.height + resizeAmount, 10 );
var rotationAmount = rotationVal; // disabled: - prevRotation;
context.clearRect( 0, 0, canvas.width, canvas.height );
// move to origin first
context.translate( moveXAmount, moveYAmount );
// rotate
context.rotate( rotationAmount * Math.PI / 180 );
// change to translate back based on image size
// (remember to compensate for scale, not shown here)
context.translate( -imageObj.width/2, -imageObj.height/2 );
context.drawImage( imageObj, 0, 0, im_width, im_height );
// reset transforms (identity matrix)
context.setTransform(1,0,0,1,0,0);
}