HTML5 缩放 canvas 以适合页面但保持 canvas 图像为特定尺寸

HTML5 scale canvas to fit page but keep canvas image at specific size

我正在创建 1200W x 300H 的特定尺寸图像,完成后我将图像传回我的服务器。我有所有的工作。

但是,在创建图像时,1200x300 的尺寸让许多用户无法使用页面 - 尤其是在移动设备上。有没有我可以使用的方法可以创建特定 1200x300 的图像,然后以较小的比例直观地显示图像以适合屏幕?

目前我能做的最好的事情是使用 DIV 和 overflow:hidden 来保持 DIV 在页面上的正确大小,但这不会缩放实际图像吃下。事实上,图像大多偏离中心,只能在屏幕上看到图像的左侧部分。

<div style="overflow:hidden;" >
  <canvas id="canvas" width="1200" height="300">
    Your browser does not support Canvas.
  </canvas>
</div>

如果我缩小 canvas 以适合页面,则创建的图像尺寸较小,而不是我需要传回服务器的尺寸。

可以这样做吗?

=============更新================

<div style="overflow:hidden;" >
   <canvas id="displayCanvas" width="1200" height="300">
      Your browser does not support Canvas.
   </canvas>
   <canvas id="realCanvas" width="1200" height="300">
      Your browser does not support Canvas.
   </canvas>                            
</div> 

#CSS

#realCanvas {
  width:100vw;
  height: 25vw ;
}

#JS

function buildBanner () {
  Debugger.log("Drawing Canvas");
  
  if(!canvasSupport()) {
      return;
  }
  
  var wCanvas = 1200 ;
  var hCanvas = 300 ;
  var wImg = 400 ;
  var hImg = 100 ;
  
  var hRatio = wCanvas  / wImg    ;
  var vRatio =  hCanvas / hImg  ;
  var ratio  = Math.min ( hRatio, vRatio );
  var centerShift_x = ( wCanvas - wImg*ratio ) / 2;
  var centerShift_y = ( hCanvas - hImg*ratio ) / 2;    
  
  var displayCanvas = document.getElementById('displayCanvas') ;
  var displayContext = displayCanvas.getContext('2d');
  
  var realCanvas = document.getElementById('realCanvas');
  var realContext = realCanvas.getContext('2d');
  
  var text1 = document.getElementById('textType1') ;
  var text2 = document.getElementById('textType2') ;
  
  if (text1.checked) {
    var bannerText = document.getElementById('cVendor').value ;
    console.log("Text1: "+ bannerText) ;
  } else if (text2.checked) {
    var bannerText = document.getElementById('cVendorName').value ;
    console.log("Text2: "+ bannerText) ;
  }
  
  var textStrokeColor = "#000000";
  var textBaseline = "middle";
  var textAlign = "center";
  
  // This is the event handler for listening for a key up event in the text box form
  // It will call the textBoxChanged function to update the text in the canvas
  
  var fontSize = document.getElementById("fontSize").value;
  var fontFaceSelect = document.getElementById("fontFace");
  var fontFace = fontFaceSelect.options[fontFaceSelect.selectedIndex].value ;
  var fontWeightSelect = document.getElementById("fontWeight");
  var fontWeight = fontWeightSelect.options[fontWeightSelect.selectedIndex].value ;
  var fontStyleSelect = document.getElementById("fontStyle");
  var fontStyle = fontStyleSelect.options[fontStyleSelect.selectedIndex].value ;
  
  var fillTypeSelect = document.getElementById("fillType");
  var fillType = fillTypeSelect.options[fillTypeSelect.selectedIndex].value ;
  var strokeTypeSelect = document.getElementById("strokeType");
  var strokeType = strokeTypeSelect.options[strokeTypeSelect.selectedIndex].value ;
  
  var textFillColor = document.getElementById("textFillColor").value ;
  var bgFillColor = document.getElementById("bgFillColor").value ;
  var imageData = document.getElementById("createImageData");
  
  realContext = drawScreen(realContext,wCanvas,hCanvas,4);       
  displayContext = drawScreen(displayContext,wImg,hImg,1) ;
  
  var imageDataDisplay = document.getElementById("imageDataDisplay");
  imageDataDisplay.value = realCanvas.toDataURL();  
  
  function drawScreen(thisContext,x,y,xSize) {
    thisContext.clearRect(0, 0, x, y);
  
    var metrics = thisContext.measureText(bannerText);
    var textWidth = metrics.width;
    var xPosition =  x / 2
    var yPosition =  y / 2;

    // Draws the Text Box
    thisContext.globalAlpha = 1.0;

    thisContext.fillStyle = bgFillColor ;
    thisContext.fillRect(0,0,x,y);
    
    // Draws the actual text
    var xFontSize = fontSize * xSize ;
    thisContext.font = fontWeight + " " + fontStyle + " " + xFontSize + "px " + fontFace;
    thisContext.textBaseline = textBaseline;
    thisContext.textAlign = textAlign;

    var tempColor;
    switch(fillType) {
      case "colorFill":
          Debugger.log("Color Fill");
          tempColor = textFillColor;
          break;
      case "linearGradient":
          Debugger.log("Linear Gradient");
          var linGradient = thisContext.createLinearGradient(xPosition-textWidth/2, yPosition, xPosition+textWidth/2, yPosition);
          linGradient.addColorStop(0, textFillColor);
          tempColor = linGradient;
          break;
      case "radialGradient":
          Debugger.log("Radial Gradient");
          var radGradient = thisContext.createRadialGradient(xPosition, yPosition, 1, xPosition, yPosition, textWidth/2);
          radGradient.addColorStop(0, textFillColor);
          tempColor = radGradient;
      break;
    }

    switch(strokeType) {
      case "fill":
          thisContext.fillStyle = tempColor;
          thisContext.fillText(bannerText, xPosition, yPosition);
          break;
      case "stroke":
          thisContext.strokeStyle = textStrokeColor;
          thisContext.strokeText(bannerText, xPosition, yPosition);
          break;
      case "both":
          thisContext.fillStyle = tempColor;
          thisContext.fillText(bannerText, xPosition, yPosition);
          thisContext.strokeStyle = textStrokeColor;
          thisContext.strokeText(bannerText, xPosition, yPosition);
          break;
    }
    return thisContext ;
  }
}

这可以通过侦听 resize 事件并相应地操纵 CSS 宽度和高度属性来完成,但是如果您的 <canvas> 元素始终具有相同的大小,则有更简单的方法.

要了解发生了什么,您需要知道通过 canvas' 元素自身属性设置的宽度和高度是 canvas 的 'real' 分辨率。 CSS 宽度和高度属性可以控制屏幕上实际呈现的尺寸。

我们想要做的是缩放 canvas 以填充浏览器的可用垂直视口 缩放它的高度,同时保持 canvas' 的原始纵横比比例。

首先我们需要计算它的纵横比:300 / 1200 = 0.25 这意味着它的高度是它的宽度的 1/4。用简单的英语来说,我们希望 canvas 宽度为视口宽度的 100%,高度为视口宽度的 25%。

幸运的是,这直接转移到 CSS vw 单元。例如100vw==100% viewport width.

所以你所要做的就是将 canvas CSS 宽度设置为 100vw 并将其高度设置为 25vw.

这是一个例子:

let image = new Image();
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
image.crossOrigin = 'anonymous';
image.onload = (e) => {
  context.drawImage(e.target, 0, 0, canvas.width, canvas.height);
}
image.src = 'https://picsum.photos/id/10/1200/300';
#canvas {
  background-color: black;
  width: 100vw;
  height: 25vw;
}
<div style="overflow:hidden;">
  <canvas id="canvas" width="1200" height="300">
    Your browser does not support Canvas.
  </canvas>
</div>