Canvas 元素溢出其容器 div

Canvas element spilling out past its container div

我正在尝试使用 Javascript 而不是 CSS 使 canvas 元素适合其容器 div,因为这样它不会拉伸绘制的任何内容在 canvas.

里面

目前,如果我刷新页面,有时 canvas 元素完全适合内部。其他时候,当我刷新时,它的宽度大于容器,而它的高度小于容器。我不知道为什么我在刷新页面时会出现这种不同的行为,即使没有调整 window.

的大小

以下是我设置 canvas 尺寸的方法:

const ctxX = canvasParent.offsetWidth - 4;
const ctxY = canvasParent.offsetHeight - 4;
canvasEl.width = ctxX;
canvasEl.height = ctxY;
const ctx = canvasEl.getContext("2d");

我读到这样的设置大小仅在容器相对定位时才有效,所以这是容器的 CSS:

display: block;
position: relative;
height: 60%;
margin-top: 2%;
border: 2px solid v.$border;

根本原因是 offsetHeightoffsetWidth 值被四舍五入,并且为它们设置 canvas 尺寸通常会导致不精确拟合,导致不足或 over-flow 的宽度或高度。由于布局引擎执行的计算,我不排除其他原因,但这个原因至关重要。

一种解决方案是使用 element.getBoundingClientRect 准确获取 parent (div) 元素的尺寸,取低于高度和宽度值的整数并使用它们设置 canvas 及其 parent 元素的维度。这可能导致 div 元素最多 1px 小于 CSS 像素宽度和高度的百分比值转换,但鉴于 canvas 尺寸属性采用整数值,这是不可避免的。

下面是一个演示此特定技术并带有警告的示例:由于调整大小而更改 canvas 尺寸将破坏现有的 canvas 内容,并且调整大小处理程序需要删除 style 设置canvas parent 上的宽度和高度,以了解调整后的尺寸。

注意:相对定位不是必需的,不包括在下面。

"use strict";
let rect = canvasParent.getBoundingClientRect();
const ctxX = Math.floor(rect.width -4);
const ctxY = Math.floor(rect.height -4);
canvasEl.width = ctxX;
canvasEl.height = ctxY;
canvasParent.style.width = ctxX + 'px';
canvasParent.style.height = ctxY + 'px';
const ctx = canvasEl.getContext("2d");
#canvasParent {
    height: 60%;
    margin-top: 2%;
    border: 2px solid orange;
    box-sizing: content-box;
}
canvas {
  background-color: forestgreen;

}

/* to see margins: */
body   { background-color: grey; }
.outer { height: 80vh; background-color: #ddd; }
<div class="outer"> <!-- outer div -->
   <div id="canvasParent"><canvas id="canvasEl"></canvas></div>
</div>

更新

  1. 在代码片段中,canvas 容器的外部容器需要具有固有高度,从中计算 #canvasParent 的百分比 height 值。

  2. 百分比 垂直 margin 值在 CSS 中很奇怪,因为它们指的是 水平 包含块的宽度百分比(参考 MDN and this question)。更糟糕的是,如果容器中的 child 个元素以百分比为单位有上边距,并且 而不是 前面是其容器块中的内容,则生成的容器宽度当遇到 child 元素时被视为零 - 导致 child.

    上没有上边距

    这就是 运行 代码段未显示应用于 #containerEl 的任何上边距的原因。如果您在 .outer 的开头放置一些文本,#containerEl 突然获得相对于插入的文本(未在代码段中显示)的上边距。

    我的结论:虽然这可能不会影响您的项目,但不要在没有充分理由的情况下对垂直边距使用百分比单位:-)