如何使HTML5画布适合动态父/弹性框容器

Xel*_*ela 9 html javascript css jquery flexbox

有没有办法在动态重新调整大小的灵活盒容器中创建画布?

最好只使用CSS解决方案,但我认为重绘需要JavaScript吗?

我认为一个解决方案可能是听取重新调整大小事件然后缩放画布以满足弹性框父级的大小然后强制重绘但我最好使用尽可能多的CSS或更干净/更少代码解决方案

当前的方法是基于CSS的,其中画布根据父flex框元素重新调整大小.在下面的屏幕截图中,图形模糊,重新定位并从画布溢出.

拉伸图像/图形溢出画布

CSS:

html,body{
            margin:0;
            width:100%;
            height:100%;
        }
        body{
            display:flex;
            flex-direction:column;
        }
header{
            width:100%;
            height:40px;
            background-color:red;
        }
        main{
            display:flex;
            flex: 1 1 auto;
            border: 1px solid blue;
            width:80vw;
        }
        canvas{
            flex: 1 1 auto;
            background-color:black;
        }
Run Code Online (Sandbox Code Playgroud)

HTML:

<header>
</header>
<main>
    <canvas id="stage"></canvas>
</main>
Run Code Online (Sandbox Code Playgroud)

使用Javascript:

$( document ).ready(function() {
    var ctx = $("#stage")[0].getContext("2d");
    ctx.strokeStyle="#FFFFFF";
    ctx.beginPath();
    ctx.arc(100,100,50,0,2*Math.PI);
    ctx.stroke();
});
Run Code Online (Sandbox Code Playgroud)

JS小提琴显示问题:https://jsfiddle.net/h2v1w0a1/

小智 16

将画布视为图像.如果将其缩放到与原始尺寸不同的尺寸,它将在某些时候显得模糊,并且可能在早期取决于浏览器选择的插值算法.对于画布,浏览器倾向于选择双线性而不是双立方体,因此与实际图像相比,模糊的风险更高.

你会希望画布中的东西尽可能地呈现出来,唯一的方法是使用JavaScript调整大小到父级,并避免使用CSS(后者适用于打印或需要"视网膜分辨率"等内容").

要获得父容器大小(以像素为单位),您可以使用getComputedStyle()(请参阅下面的更新):

var parent = canvas.parentNode,
    styles = getComputedStyle(parent),
    w = parseInt(styles.getPropertyValue("width"), 10),
    h = parseInt(styles.getPropertyValue("height"), 10);

canvas.width = w;
canvas.height = h;
Run Code Online (Sandbox Code Playgroud)

小提琴

(注意:目前Chrome似乎在计算flex方面存在一些问题)

更新

这是一个更简单的方法:

var rect = canvas.parentNode.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
Run Code Online (Sandbox Code Playgroud)

小提琴

  • 在画布上添加 style="position:absolute" 使其对我来说也很有效。 (3认同)
  • 第二个小提琴链接坏了。 (2认同)

Tem*_*fif 5

The only CSS solution I can think about is the use of object-fit:none (related: How does object-fit work with canvas element?)

$(document).ready(function() {
  var ctx = $("#stage")[0].getContext("2d");
  ctx.strokeStyle = "#FFFFFF";
  ctx.beginPath();
  ctx.arc(100, 100, 50, 0, 2 * Math.PI);
  ctx.stroke();
});
Run Code Online (Sandbox Code Playgroud)
html,
body {
  margin: 0;
  width: 100%;
  height: 100%;
}

body {
  display: flex;
  flex-direction: column;
}

header {
  width: 100%;
  height: 40px;
  background-color: red;
}

main {
  display: flex;
  flex: 1 1 auto;
  border: 1px solid blue;
  width: 80vw;
}

canvas {
  flex: 1 1 auto;
  background-color: black;
  object-fit:none;
  object-position:top left;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
</header>
<main>
  <canvas id="stage"></canvas>
</main>
Run Code Online (Sandbox Code Playgroud)