如何旋转整个画布和同时绘制到画布中的图像?

时间:2019-04-10 07:18:48

标签: javascript canvas

首先,使用以下代码上传比宽高小的图像。

//<![CDATA[
/* js/external.js */
var doc, M, I;
addEventListener('load', function(){
doc = document;
M = function(tag){
  return doc.createElement(tag);
}
I = function(id){
  return doc.getElementById(id);
}
var canvas = I('canvas'), ctx;
I('upload').onchange = function(){
  var files = this.files, file, fr, img;
  if(files.length){
    file = files[0]; fr = new FileReader; img = M('img');
    fr.onload = function(){
      img.onload = function(){
        canvas.width = this.width; canvas.height = this.height;
        ctx = canvas.getContext('2d'); ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
      }
      img.src = this.result;
    }
    fr.readAsDataURL(file);
  }
}
});
//]]>
/* css/external.css */
*{
  float:left; clear:left;
}
#canvas{
  margin-top:10px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>canvas rotate</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script type='text/javascript' src='js/external.js'></script>
  </head>
<body>
  <input id='upload' type='file' accept='image/*' />
  <canvas id='canvas' width='0' height='0'></canvas>
</body>
</html>

您可以看到图像正确显示在画布中。不过,那不是我的问题。我实际上是在尝试同时旋转整个画布尺寸和画布内容。如果它是正方形,那将是没有问题的,因为我可以像这样ctx.save(); cxt.translate(halfImageWidth, halfImageHeight); ctx.rotate(Math.PI*90/180); ctx.translate(-halfImageWidth, -halfImageHeight); ctx.drawImage(imageContext, 0, 0, imageWidth, imageHeight);来获取一半的高度和宽度。

这是我认为可行的方法,但无效:

//<![CDATA[
/* js/external.js */
var doc, M, I;
addEventListener('load', function(){
doc = document;
M = function(tag){
  return doc.createElement(tag);
}
I = function(id){
  return doc.getElementById(id);
}
var canvas = I('canvas'), ctx;
I('upload').onchange = function(){
  var files = this.files, file, fr, img;
  if(files.length){
    file = files[0]; fr = new FileReader; img = M('img');
    fr.onload = function(){
      img.onload = function(){
        canvas.width = this.height; canvas.height = this.width;
        ctx = canvas.getContext('2d'); ctx.save(); ctx.rotate(Math.PI*90/180);
        ctx.translate(-canvas.width, 0); ctx.drawImage(this, 0, 0, canvas.width, canvas.height); ctx.restore();
      }
      img.src = this.result;
    }
    fr.readAsDataURL(file);
  }
}
});
//]]>
/* css/external.css */
*{
  float:left; clear:left;
}
#canvas{
  margin-top:10px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>canvas rotate</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script type='text/javascript' src='js/external.js'></script>
  </head>
<body>
  <input id='upload' type='file' accept='image/*' />
  <canvas id='canvas' width='0' height='0'></canvas>
</body>
</html>

我发现通过在旋转之前不进行平移,我的原点是左上角,因此我应该能够在旋转后设置负原点,但这是行不通的。如果有人可以显示并解释如何正确执行此操作,将不胜感激。

PS

我已经考虑过CSS旋转,但是由于我确实在使用数据,因此这不是我的解决方案。

1 个答案:

答案 0 :(得分:2)

如果您说过只需旋转90度,那就很简单了。

您图像的宽度将成为画布的高度,其高度将成为画布的宽度。

从那里您只需应用通常的

translate(target-center-x, target-center-y)
rotate(angle)
drawImage(img, -transform-origin, -transform-origin)

fileinput.onchange = e => {
  const img = new Image();
  img.onload = e => draw(img);
  img.src = URL.createObjectURL(fileinput.files[0]);
};

function draw(img) {
  const ctx = canvas.getContext('2d');
  canvas.width = img.height;
  canvas.height = img.width;
  // move to center of the canvas
  ctx.translate(canvas.width / 2, canvas.height / 2);
  ctx.rotate(Math.PI / 2);
  // set the transform origin at center of the image
  ctx.drawImage(img, -img.width / 2, -img.height / 2);
}
<input type="file" id="fileinput">
<canvas id="canvas"></canvas>