CANVAS旋转图片,可旋转顺序为什么不对呢?

先上代码,直接可运行,不论是左旋转还是右旋转,顺序都不对。请问怎么解决这一问题?最后我需要返回base64位替换img里的值。

<div class="content">
    <div class="box"><img src="图片地址" /><div class="rotate_img">旋转</div></div>
    ...有N个相同的DIV...
    <div class="box"><img src="图片地址" /><div class="rotate_img">旋转</div></div>
</div>
// 点击rotate_img,即可旋转对应box中的图片

<!-- js 部分 -->
<script>
function rotateImg(pid, direction) {  
    //最小与最大旋转方向,图片旋转4次后回到原方向  
    var min_step = 0;  
    var max_step = 3;  
    var img = document.getElementById(pid);  
    if (img == null)return;  
    //img的高度和宽度不能在img元素隐藏后获取,否则会出错  
    var height = img.height;  
    var width = img.width;  
    var step = img.getAttribute('step');  
    if (step == null) {  
        step = min_step;  
    }  
    if (direction == 'right') {
        step++;  
        //旋转到原位置,即超过最大值  
        step > max_step && (step = min_step);  
    } else {  
        step--;  
        step < min_step && (step = max_step);  
    }  
    img.setAttribute('step', step);  
    var canvas = document.getElementById('pic_' + pid);  
    if (canvas == null) {  
        // img.style.display = 'none';  
        canvas = document.createElement('canvas');  
        canvas.setAttribute('id', 'pic_' + pid);
        // var url = canvas.toDataURL();
        // img.parentNode.appendChild(canvas);  
    }
    //旋转角度以弧度值为参数  
    var degree = step * 90 * Math.PI / 180;  
    var ctx = canvas.getContext('2d');  
    switch (step) {
        case 0:  
            canvas.width = width;  
            canvas.height = height;  
            ctx.drawImage(img, 0, 0);  
            break;  
        case 1:  
            canvas.width = height;  
            canvas.height = width;
            ctx.rotate(degree);  
            ctx.drawImage(img, 0, -height);  
            break;  
        case 2:  
            canvas.width = width;  
            canvas.height = height;  
            ctx.rotate(degree);  
            ctx.drawImage(img, -width, -height);  
            break;  
        case 3:  
            canvas.width = height;  
            canvas.height = width;  
            ctx.rotate(degree);  
            ctx.drawImage(img, -width, 0);  
            break;
    }
    var url = canvas.toDataURL();
    img.src = url;
}
</script>

先谢谢啦!~

阅读 3.8k
4 个回答

我想告诉你 how and why,所以写了个原理向的小 demo,如果代码还是有疑惑,留言让我知道 (^ ^)

transform2d

const matrixHelper = {
  translate(tx, ty) {
    return [1, 0, 0, 0, 1, 0, tx, ty, 1];
  },
  rotate(angle) {
    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    return [cos, -sin, 0, sin, cos, 0, 0, 0, 1];
  },
  scale(sx, sy) {
    return [sx, 0, 0, 0, sy, 0, 0, 0, 1];
  },
  mult(a, b) {
    const ret = [];
    for (let y = 0; y < 3; y++) {
      for (let x = 0; x < 3; x++) {
        let sum = 0;
        for (let i = 0; i < 3; i++) {
          sum += b[i + y * 3] * a[x + i * 3];
        }
        ret[x + y * 3] = sum;
      }
    }
    return ret;
  },
  setTransform(ctx, m) {
    ctx.setTransform(m[0], m[1], m[3], m[4], m[6], m[7]);
  },
};

function translateImage(canvas, image, deg, scale = 0.5) {
  const ctx = canvas.getContext("2d");
  const width = image.width;
  const height = image.height;
  const angle = (deg / 180) * Math.PI;

  let m = matrixHelper.scale(scale, scale);
  m = matrixHelper.mult(m, matrixHelper.rotate(angle));
  m = matrixHelper.mult(m, matrixHelper.translate(-width >> 1, -height >> 1));

  const translate = (x, y) => ({
    x: x * m[0] + y * m[3] + 1 * m[6],
    y: x * m[1] + y * m[4] + m[7],
  });
  const upLeft = translate(0, 0);
  const upRight = translate(width, 0);
  const downLeft = translate(0, height);
  const downRight = translate(width, height);
  const newWidth =
    Math.max(upLeft.x, upRight.x, downLeft.x, downRight.x) -
    Math.min(upLeft.x, upRight.x, downLeft.x, downRight.x);
  const newHeight =
    Math.max(upLeft.y, upRight.y, downLeft.y, downRight.y) -
    Math.min(upLeft.y, upRight.y, downLeft.y, downRight.y);

  [canvas.width, canvas.height] = [newWidth, newHeight];
  m = matrixHelper.translate(newWidth >> 1, newHeight >> 1);
  m = matrixHelper.mult(m, matrixHelper.scale(scale, scale));
  m = matrixHelper.mult(m, matrixHelper.rotate(angle));
  m = matrixHelper.mult(m, matrixHelper.translate(-width >> 1, -height >> 1));
  matrixHelper.setTransform(ctx, m);
  ctx.drawImage(image, 0, 0);
}

async function bootstrap() {
  const canvas = document.createElement("canvas");
  document.body.appendChild(canvas);
  const image = new Image();
  image.src =
    "https://c-ssl.duitang.com/uploads/item/201702/17/20170217101328_L4zQj.thumb.1000_0.jpeg";
  await new Promise((resolve) => (image.onload = resolve));
  let deg = 0;
  setInterval(() => {
    translateImage(canvas, image, deg++, 0.5);
  }, 100);
}
bootstrap();

算了,我整了半天也搞不明白,这样吧
终极大招,别旋转你的图像了,旋转你的元素吧!


我好像终于搞明白了,之前想复杂了

var canvas = document.getElementsByTagName('canvas')[0]; 
var ctx = canvas.getContext('2d');
var img = document.getElementById("testImg"); 
var canvasW = canvas.width;
var canvasH = canvas.height;
// 移动旋转中心点到(0,0)点
// 重点只有这一句
ctx.translate(canvasW/2, canvasH/2); 
ctx.drawImage(img,0,0); 
    
function rotateImg(num) { 
    ctx.clearRect(0, 0, canvasW, canvasH);
    // 之前弄错的原因是在叠加角度了 QTZ 突然意识到拿内容会叠加的
    ctx.rotate( (90 * num) *Math.PI/180);
    ctx.drawImage(img, 0, 0);  
}

旋转中心的问题吧,应该将旋转中心移动到图片中心:ctx.translate(widrh/2,height/2)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题