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>

先谢谢啦!~

阅读 187
评论
    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();