Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
351 views
in Technique[技术] by (71.8m points)

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>

先谢谢啦!~


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

我想告诉你 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();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...