如何以正确的方式旋转画布

时间:2018-03-02 09:25:57

标签: javascript canvas

我有一张想要剪裁的图片。

因此,我用较暗的背景创建了canvas as overlay,然后在鼠标移动时我在画布上画了一个rect,在那个矩形中我清除了黑暗的背景。这看起来如下:

enter image description here

因此,将裁剪没有背景的区域。

我的代码如下:

var canvas = document.getElementById('canvas');
var img = document.getElementById('photo');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var update = true; // when true updates canvas
var original_source = img.src;
img.src = original_source;
var deg = 0;
var image_rotate_angle = 90;

document.getElementById('right').addEventListener("click", rotateRight, false);
document.getElementById('left').addEventListener("click", rotateLeft, false);

function rotateRight(){
	deg = deg + image_rotate_angle;
	img.style.transform = "rotate(" + deg + "deg)";
  canvas.style.transform = "rotate(" + deg + "deg)";
}

function rotateLeft(){
	deg = deg - image_rotate_angle;
	img.style.transform = "rotate(" + deg + "deg)";
  canvas.style.transform = "rotate(" + deg + "deg)";
}

function init() {
    img.addEventListener('load', function(){
        canvas.width = img.width;
        canvas.height = img.height;
        canvas.addEventListener('mousedown', mouseDown, false);
        canvas.addEventListener('mouseup', mouseUp, false);
        canvas.addEventListener('mousemove', mouseMove, false);
    });
    
    // start the rendering loop
    requestAnimationFrame(updateCanvas);
}

// main render loop only updates if update is true
function updateCanvas(){
  if(update){
      drawCanvas();
      update = false;
  }

  requestAnimationFrame(updateCanvas);
}

// draws a rectangle with rotation 
function drawRect(){
		ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
}

// clears canvas sets filters and draws rectangles
function drawCanvas(){    
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'rgba(32, 32, 32, 0.7)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    drawRect()
}

// create new rect add to array 
function mouseDown(e) {
    rect = {
      startX : e.offsetX,
      startY : e.offsetY,
      w : 1,
      h : 1
    };
    drag = true;
}

function mouseUp() { drag = false; update = true; }

function mouseMove(e) {
    if (drag) {
        rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        rect.h = (e.pageY - this.offsetTop) - rect.startY;
        update = true;
    }
}

init();
canvas{
  position: absolute;
  left: 0; 
  right: 0; 
  top: 0; 
  bottom: 0; 
  display:inline-block;
  background:rgba(0,0,0,0.3);
}
<div style="margin-bottom: 15px;">
  <button id="left">Rotate Reft</button>
  <button id="right">Rotate Right</button>
</div>
<div style="position: relative; overflow: hidden;display:inline-block;">
    <img id="photo" src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg"/>
    <canvas id="canvas"></canvas>
</div>

我还有两个用于旋转图像的按钮。我有问题。解决方案可能很明显,但我没有看到它。

  • 如果我绘制矩形然后旋转图像,我也会旋转图像和画布,然后旋转后矩形停留在同一个位置。这就是我想要的,并且工作正常。

  • 问题是我首先旋转图像然后尝试绘制矩形。然后矩形不是应该绘制的,它朝相反方向。

Here is the fiddle.

知道怎么解决吗?

1 个答案:

答案 0 :(得分:0)

您可能只是根据图像的大小来获取数字以找到新x和y所在的位置,但我想在画布上实际绘制所有内容并旋转其更易于管理转换矩阵。

但这意味着您的代码会发生一些变化:

您必须使用合成(或使用&#39;偶数&#39; fill-rule,like I already shown you)绘制图像。
您还必须使drawCanvas功能更加复杂,以便仅在需要时(当用户点击&#34;旋转&#34;按钮时)旋转

&#13;
&#13;
var canvas = document.getElementById('canvas');
var img = new Image();
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var update = true; // when true updates canvas
var angle = 0;

document.getElementById('right').addEventListener("click", rotateRight, false);
document.getElementById('left').addEventListener("click", rotateLeft, false);

function rotateRight() {
  angle += Math.PI / 2;
  drawCanvas(true); // let know we're from rotate function
}

function rotateLeft() {
  angle -= Math.PI / 2;
  drawCanvas(true);
}

function init() {
  img.addEventListener('load', function() {
    canvas.width = img.width;
    canvas.height = img.height;
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);
  });

  // start the rendering loop
  requestAnimationFrame(updateCanvas);
}

// main render loop only updates if update is true
function updateCanvas() {
  if (update) {
    drawCanvas(false); // don't rotate the rectangle here
    update = false;
  }

  requestAnimationFrame(updateCanvas);
}

// draws a rectangle with rotation 
function drawRect() {
  ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
}

// clears canvas sets filters and draws rectangles
function drawCanvas(fromRotate) {
  // reset the transformation matrix to its defaults
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  ctx.fillStyle = 'rgba(32, 32, 32, 0.7)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // for the rectangle, rotate only if we are using previously set rect
  if (fromRotate) {
    // Move to center
    ctx.setTransform(1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
    // rotate by the current angle
    ctx.rotate(angle);
    // move back to what is now top right corner
    ctx.translate(-canvas.width / 2, -canvas.height / 2);
  }
  drawRect();
  // draw the image behind the overlay
  ctx.globalCompositeOperation = 'destination-over';
  // rotate the whole context every time for the image
  ctx.setTransform(1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
  // rotate by the current angle
  ctx.rotate(angle);
  // draw the image, from center
  ctx.drawImage(img, -img.width / 2, -img.height / 2);

}

// create new rect add to array 
function mouseDown(e) {
  rect = {
    startX: e.offsetX,
    startY: e.offsetY,
    w: 1,
    h: 1
  };
  drag = true;
}

function mouseUp() {
  drag = false;
  update = true;
}

function mouseMove(e) {
  if (drag) {
    rect.w = (e.offsetX - this.offsetLeft) - rect.startX;
    rect.h = (e.offsetY - this.offsetTop) - rect.startY;
    update = true;
  }
}

init();
img.src = 'https://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
&#13;
<div style="margin-bottom: 15px;">
  <button id="left">Rotate Reft</button>
  <button id="right">Rotate Right</button>
</div>
<div style="position: relative; overflow: hidden;display:inline-block;">

  <canvas id="canvas"></canvas>
</div>
&#13;
&#13;
&#13;