英文:
How do I make a canvas fill a div while keeping its aspect ratio?
问题
我有一个位于弹性盒子内的画布元素,可能会被调整大小。如何使画布填充可用空间,同时保持其纵横比(2/3)且不被裁切?(我想更改CSS尺寸,而不是画布分辨率)。
我尝试过使用object-fit: contain
和clamp(...)
,但无法获得我想要的结果。要么画布无法保持其纵横比,要么它会超出其容器。
这是我一直在尝试的精简版本:https://jsfiddle.net/mwq4502v/。
我不确定如何最好地实现这一点,所以非常感谢任何帮助!
英文:
I have a canvas element inside a flexbox that may be resized.
How do I get the canvas to fill the available space without losing its aspect ratio (2/3), and without being cut off?
(I want to change the CSS dimensions, not the canvas resolution).
I've tried using object-fit: contain
and clamp(...)
, but I can't get the results I want. Either the canvas doesn't maintain its aspect ratio, or it grows outside its container.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
body {
margin: 0;
}
#mainContent {
background: grey;
height: 100vh;
display: flex;
flex-wrap: nowrap;
align-items: center;
}
#someOtherElem {
background: red;
width: 200px;
height: 200px;
margin-left: 1rem;
}
#canvasContainer {
display: flex;
flex: 1;
height: 100%;
justify-content: center;
align-items: center;
}
canvas {
width: calc(100% - 2rem);
height: calc(100% - 2rem);
background: green;
object-fit: contain;
}
<!-- language: lang-html -->
<div id="mainContent">
<div id="someOtherElem"></div>
<div id="canvasContainer">
<canvas height="300" width="200"></canvas>
</div>
</div>
<!-- end snippet -->
Here's a stripped-down version of what I've been trying: https://jsfiddle.net/mwq4502v/.
I'm not sure what the best way to achieve this is, so any help would be greatly appreciated!
答案1
得分: 2
你可以为canvas
指定一个aspect-ratio
为2 / 3
,宽度为100%
或<parent-height> * 2 / 3
,以较小者为准。
canvas {
aspect-ratio: 2 / 3;
width: min(100%, 100vh * 2 / 3);
/* ...或者高度: min(100%, calc(100vw - 210px) * 3 / 2). 相同的精神。 */
}
一些数学计算:
设容器的宽度和高度分别为w
和h
。由于canvas需要尽可能大,它将始终触碰容器的至少两个边界(或四个边界),这意味着其大小可以是w / (w / (2 / 3))
或(h * 2 / 3) / h
,这取决于容器的大小。
w / h
> 2 / 3
:
◄──────────── w ────────────►
┌────────┬─────────┬────────┐ ▲
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
│ │ │ │ h
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
└────────┴─────────┴────────┘ ▼
◄ (h*2/3) ►
w / h
< 2 / 3
:
◄─── w ───►
┌─────────┐ ▲
│ │ │
▲ ├─────────┤ │
│ │ │ │
│ │ │ │
(w*3/2) │ │ h
│ │ │ │
│ │ │ │
▼ ├─────────┤ │
│ │ │
└─────────┘ ▼
这意味着宽度需要是min(w, h * 2 / 3)
,在CSS中写成min(100%, 100vh * 2 / 3)
。
尝试一下:
<div id="mainContent">
<div id="someOtherElem"></div>
<div id="canvasContainer">
<canvas></canvas>
</div>
</div>
英文:
You can specify an aspect-ratio
of 2 / 3
for canvas
and a width of 100%
or <parent-height> * 2 / 3
, whichever smaller.
canvas {
aspect-ratio: 2 / 3;
width: min(100%, 100vh * 2 / 3);
/* ...or height: min(100%, calc(100vw - 210px) * 3 / 2). Same spirit. */
}
Some math:
Let the width and height of the container be w
and h
, correspondingly. Since the canvas needs to be as large as possible it will always touch at least two borders of the container (or all 4), which means its size can be either w / (w / (2 / 3))
or (h * 2 / 3) / h
, depends on the size of the container.
w / h
> 2 / 3
:
◄──────────── w ────────────►
┌────────┬─────────┬────────┐ ▲
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
│ │ │ │ h
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
└────────┴─────────┴────────┘ ▼
◄ (h*2/3) ►
w / h
< 2 / 3
:
◄─── w ───►
┌─────────┐ ▲
│ │ │
▲ ├─────────┤ │
│ │ │ │
│ │ │ │
(w*3/2) │ │ h
│ │ │ │
│ │ │ │
▼ ├─────────┤ │
│ │ │
└─────────┘ ▼
This means the width needs to be min(w, h * 2 / 3)
or, in CSS, min(100%, 100vh * 2 / 3)
.
Try it:
<!-- begin snippet: js hide: true console: false babel: false -->
<!-- language: lang-css -->
canvas {
aspect-ratio: 2 / 3;
width: min(100%, 100vh * 2 / 3);
}
/* Demo only */
#canvasContainer {
outline: 1px solid #000; /* Just so we know where it is */
}
body {
margin: 0;
}
#mainContent {
display: flex;
align-items: center;
height: 100vh;
}
#someOtherElem {
margin-left: 1rem;
width: 200px;
height: 200px;
background: red;
}
#canvasContainer {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
canvas {
background: green;
}
<!-- language: lang-html -->
<div id="mainContent">
<div id="someOtherElem"></div>
<div id="canvasContainer">
<canvas></canvas>
</div>
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论