【问题标题】:How can i move rotated canvas image whitout disorientation?如何移动旋转画布图像而不会迷失方向?
【发布时间】:2015-05-18 19:14:42
【问题描述】:

我在画布中加载了一张图片。旋转后,我无法(拖动)正确移动图像。实际上,它会移动,但它会根据图像的坐标平面移动。因此,将旋转 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:您可以使用左侧的滑块旋转图像。底部滑块用于缩放。如果图像没有出现在第一次加载中,请重新运行小提琴。

【问题讨论】:

    标签: javascript jquery canvas html5-canvas filereader


    【解决方案1】:

    绘制后重置转换。鼠标事件在应用到画布上下文时也会被转换,因此只有在绘图时才使用转换可以解决这个问题。但是,这也要求代码使用绝对值,例如:

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

    Modified fiddle

    您可能需要使用逆矩阵。当我们可以根据当前的转换矩阵取出一个 SVGMatrix 时,这将在以后变得可用,但目前还没有广泛使用。否则,逆矩阵将应用于鼠标 x/y 位置,顾名思义,逆主变换的效果。

    可以选择使用自定义转换矩阵解决方案来跟踪转换(我会邀请您查看我自己的方法here,它是免费的)。

    PS:还修复了图像加载问题(见小提琴)。

    【讨论】:

    • 为好答案点赞。另外,@Skeletor:我强烈推荐 K3N 的转换库。如果您将来需要针对转换后的图像对鼠标进行点击测试,那么 K3N 的库将非常方便。 :-)
    【解决方案2】:
    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);
    } 
    

    https://codepen.io/niko8888/pen/NWKXgdX?editors=0010

    【讨论】:

      猜你喜欢
      • 2014-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      • 2018-11-25
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多