Canvas 填充视口并保持图像比例

Canvas fill viewport and keep image ratio

我试图让 canvas 区域和图像填充视口而不拉伸图像,并在调整页面大小时保持其纵横比。下面是我当前的代码。

      var ctx = $("#demo")[0].getContext("2d"),
      img = new Image(),
      radius = 35,
      blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";

      img.src = blurryImageSrc;

      $(img).on("load", function() {

      resizeCanvas();

       $("#demo").on("mousemove", function(e) {
        erase(getXY(e));
       });

       $("#reset").on("click", function() {
        ctx.globalCompositeOperation = "source-over";
        ctx.drawImage(img, 0, 0);
        ctx.globalCompositeOperation = "destination-out";
       });

       ctx.drawImage(img, 0, 0, window.innerWidth,  window.innerHeight);
       ctx.globalCompositeOperation = "destination-out";
     });

    function getXY(e) {
     var r = $("#demo")[0].getBoundingClientRect();
     return { x: e.clientX - r.left, y: e.clientY - r.top };
    }

    function erase(pos) {
     ctx.beginPath();
     ctx.arc(pos.x, pos.y, radius, 0, 2 * Math.PI);
     ctx.closePath();
     ctx.fill();
    }


      var can = document.getElementById('demo');
      function resizeCanvas() {
        can.style.width = window.innerWidth + 'px';
         setTimeout(function() {
          can.style.height = window.innerHeight + 'px';
         }, 0);
      }

      window.onresize = resizeCanvas;

      resizeCanvas();

https://jsfiddle.net/65fph0mn/8/

我在这里等待图片加载。然后我可以为 window 调整大小添加事件监听器并调用函数 resizeCanvas。然后此函数将调整 canvas 的大小并在 canvas.

中绘制图像

每次 window 调整大小时都必须重新绘制图像。

为了保持纵横比,图像的高度是根据缩放后的宽度计算的。

const canvas = document.getElementById('demo');

var ctx = canvas.getContext("2d"),
  img = new Image(),
  blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";

img.src = blurryImageSrc;

img.addEventListener("load", e => {
  window.addEventListener('resize', resizeCanvas);
  resizeCanvas();
});

function paint() {
  var newHeight = Math.round(img.width/canvas.width*img.height);
  ctx.drawImage(img, 0, 0, img.width, newHeight, 0, 0, canvas.width, canvas.height);
}

function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  paint();
}
body {
  background: lightgrey;
  margin: 0;
}

.container {
  position: relative;
  background: blue;
  width: 100vw;
  height: 100vh;
}

#demo {
  cursor: crosshair;
  width: 100vw;
  height: 100vh;
}
<div class="container">
  <canvas id="demo" width="640" height="640"></canvas>
</div>

要保持​​图像的正确比例,您需要查询它的 'natural' 宽度和高度。 image 对象本身有两个用于此目的的属性:naturalWidthnaturalHeight.

图片加载完成后,您必须根据浏览器的尺寸 window 和图片的较长边来决定缩放图片的比例。

让我们看一个简单的例子。假设您的浏览器 window 的宽度为 1200 像素,图像为 250。如果我们现在将 1200 除以 250,我们得到 4.8 - 这就是我们需要乘以图像宽度 和 [=31= 的因数] 高度以在一个方向上填充当前浏览器 window,同时保持其正确的纵横比。

这是一个例子:

var ctx = $("#demo")[0].getContext("2d"),
  img = new Image(),
  radius = 35,
  blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";

/// setup logic
img.src = blurryImageSrc;

$(img).on("load", function() {
  resizeCanvas();
});

var can = document.getElementById('demo');

function resizeCanvas() {
  can.width = window.innerWidth;
  can.height = window.innerHeight;
  if (img.width > 0) {
    let factor = can.width / img.naturalWidth * img.naturalHeight > window.innerHeight ? can.height / img.naturalHeight : can.width / img.naturalWidth;
    ctx.drawImage(img, 0, 0, img.naturalWidth * factor, img.naturalHeight * factor);
  }
}

window.onresize = resizeCanvas;

resizeCanvas();
body {
  background: lightgrey;
  margin: 0;
}

.container {
  position: relative;
  background: blue;
  width: 100vw;
  height: 100vh;
}

#demo {
  cursor: crosshair;
  width: 100vw;
  height: 100vh;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="container">
  <canvas id="demo" width=640 height=640></canvas>
</div>