【问题标题】:HTML5 scale canvas to fit page but keep canvas image at specific sizeHTML5 缩放画布以适应页面,但将画布图像保持在特定大小
【发布时间】:2022-01-28 20:36:08
【问题描述】:

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

但是,在创建图像时,1200x300 大小的图像会让许多用户无法访问页面 - 特别是在移动设备上。有没有什么方法可以创建特定 1200x300 的图像,然后以较小的比例直观地显示图像以适应屏幕?

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

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

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

可以这样做吗?

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

<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 ;
  }
}

【问题讨论】:

    标签: html css html5-canvas


    【解决方案1】:

    这可以通过监听 resize 事件并相应地操作 CSS 宽度和高度属性来完成,但如果您的 &lt;canvas&gt; 元素始终大小相同,则有一种更简单的方法。

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

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

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

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

    因此,您只需将画布 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>

    【讨论】:

    • 从头开始创建图像时,我无法让它工作。创建的图像来自用户输入、文本、颜色、字体等。实际上,它看起来只是包装器 DIV 使用vw 设置了宽度/高度 - 这是我为 DIV 添加到我的 CSS 中的,但是1200x300 图像未按比例缩小。我还能在 OP 中为您提供什么?
    • 我暂时做的是创建两个画布 - 一个为实际大小 (1200x300),另一个为 25% (400x100)。我显示较小的,隐藏真正的 - 提交表单时,将realCanvas.toDataURL(); 发送到服务器。它不漂亮,但到目前为止,它是我唯一可以缩小全尺寸图像的东西。
    • 如果没有看到您的实际 html 布局,恐怕这更像是在浑水中钓鱼。听起来好像您已将 100vw 25vw 应用于错误的元素,就像您所说的“包装器 DIV”。 &lt;canvas&gt; 元素需要这些样式。
    • 它被应用于画布,虽然你是对的,但我的评论确实暗示它被应用于包装 DIV,对此感到抱歉。 displayCanvas / realCanvas 是我正在工作的临时解决方案,CSS 应用于 realCanvas - 但它没有缩小。我在 OP 的更新中发布了我的所有代码。
    • 在保持纵横比的同时缩小画布显示的另一种方法是应用 CSS 变换:#mycanvas { transform:scale(0.4) }
    猜你喜欢
    • 2015-09-15
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多