<canvas>的宽高比行为 - 内部尺寸和元素大小

时间:2015-05-27 13:26:03

标签: css html5 canvas aspect-ratio

如您所知,HTML5中的<canvas>元素具有内部大小,通过elm.widthelm.height设置,其中elm是DOM元素。

DOM中的元素本身可以有不同的框大小,通过CSS设置。

当两者不同时,浏览器会自动拉伸 <canvas>的内容以适合内容框大小。可以在没有额外元素的情况下调整此行为吗?是否可以将其设置为background-size: contain,以便保持内部画布大小的宽高比​​?

据我所知,没有标准的方法可以做到这一点,因此也接受了特定于webkit的黑客攻击。但是如果根本没有办法做到这一点,那么使用包装元素做什么是最优雅的(我们都知道我们可以在调整大小时包装元素并通过JS调整它)? / p>

我能想到的一个解决方案实际上是使用background-size: containbackground: element(),但这是特定于Firefox的,我正在寻找一个WebKit解决方案。

附带问题,元素框和画布内部尺寸的差异是否会影响性能?如果是这样,多少钱?

1 个答案:

答案 0 :(得分:2)

是的,有一个new CSS property called object-fit。这允许您将内容设置为例如cover,然后强制纵横比与填充DOM框同时保持。

只需将此规则添加到canvas元素:

canvas {
  object-fit: cover;
  }

snapshot

支持

已更新)它是(部分)supported in Safari,但不在IE中。 Opera Mini需要-o-前缀。

似乎无法使用可能与这些问题相关的Chrome中的WebGL画布(或视频):issue #1issue #2issue #3

作为后备,大小可以是calculated manually。这可以与drawImage一起使用。如果drawImage不是一个选项,它将需要一个包含溢出设置为隐藏的包装元素才能工作。

实施例

下面的两个canvas都使用默认的位图大小为300x150。然后通过定义CSS大小300x300像素来拉伸它们。

通常这会使圆圈成为椭圆形。但是,右侧的画布将使用新的object-fit规则设置为cover,位图将根据宽高比进行缩放,因此我们仍然会得到一个圆圈,但当然我们也会松开一些边缘(以及清晰度)。

var ctx1 = document.getElementById("c1").getContext("2d");
var ctx2 = document.getElementById("c2").getContext("2d");

drawCircle(ctx1, 150, 75, 70);   // draw circle to stretched canvas 1
drawCircle(ctx2, 150, 75, 70);   // draw circle to object-fit/cover canvas 2

function drawCircle(ctx, x, y, r) {
  ctx.moveTo(x + r, y);
  ctx.arc(x, y, 70, 0 , 6.28);
  ctx.closePath();
  ctx.stroke();
}
#c1, #c2 {
    width:300px;
    height:300px;
    }
#c2 {
    -o-object-fit: cover;  /* for Opera Mini */
    object-fit: cover;     /* W3C version (incl. FF/webkit) */
    }
<canvas id="c1"></canvas><canvas id="c2"></canvas>