使用 CSS 时画布会被拉伸,但“宽度”/“高度”属性正常
Posted
技术标签:
【中文标题】使用 CSS 时画布会被拉伸,但“宽度”/“高度”属性正常【英文标题】:Canvas is stretched when using CSS but normal with "width" / "height" properties 【发布时间】:2020-06-29 05:25:48 【问题描述】:我有 2 个画布,一个使用 html 属性 width
和 height
来调整大小,另一个使用 CSS:
<canvas id="compteur1" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>
Compteur1 显示应该是这样,但不是 compteur2。内容是使用 javascript 在 300x300 画布上绘制的。
为什么会有显示差异?
【问题讨论】:
【参考方案1】:width
和 height
属性似乎决定了画布坐标系的宽度或高度,而 CSS 属性只决定了它的显示框的大小。
这在HTML specification中有解释:
canvas
元素有两个属性来控制元素位图的大小:width
和height
。这些属性在指定时必须具有有效的非负整数。 解析非负整数的规则必须用于获取它们的数值。如果缺少某个属性,或者如果解析其值返回错误,则必须使用默认值。width
属性默认为 300,height
属性默认为 150。
【讨论】:
确实.. 我一直认为像“width”和“height”这样的直接属性在最近的 html 版本中被弃用了.. 哦,显然它实际上在whatwg.org/specs/web-apps/current-work/multipage/…(#attr-canvas-width
部分)描述得相当好。问题是我之前点击了错误的width
,而是转到了#dom-canvas-width
部分。提交w3.org/Bugs/Public/show_bug.cgi?id=9469关于它。
拥有一个看起来很像但与另一个(css 宽度、高度)根本不同的 API。哇。
当您希望内部坐标系不同时,区分这些很重要。 (即用于视网膜显示器或 8 位风格的游戏)
这真是令人困惑。我们试图在css中设置宽度和高度。我们花了 2 天的时间拉扯头发来了解这两种关于宽度和高度的不同解释。哇...【参考方案2】:
要设置你需要的width
和height
,你可以使用
canvasObject.setAttribute('width', '475');
【讨论】:
+1el.setAttribute('width', parseInt($el.css('width')))
成功了,谢谢
如果我想让我的画布有一个相对大小怎么办?也就是说,如何模仿width: 100%;
的css属性?
很好的答案,但不要忘记添加 canvasObject.setAttribute('height', '123') !
我认为你不需要使用 .setAttribute() 我一直使用 .width 和 .height 属性
使用getComputedStyle的纯JavaScript(不带jQuery)版本:canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));
。重复高度。【参考方案3】:
对于 <canvas>
元素,width
和 height
的 CSS 规则设置将被绘制到页面的画布元素的实际大小。另一方面,width
和 height
的 HTML 属性设置画布 API 将使用的坐标系或“网格”的大小。
例如,考虑这个 (jsfiddle):
var ctx = document.getElementById('canvas1').getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 30, 30);
var ctx2 = document.getElementById('canvas2').getContext('2d');
ctx2.fillStyle = "red";
ctx2.fillRect(10, 10, 30, 30);
canvas
border: 1px solid black;
<canvas id="canvas1" style="width: 50px; height: 100px;" ></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" ></canvas>
相对于画布元素的内部坐标,两者都绘制了相同的东西。但在第二个画布中,红色矩形的宽度将是原来的两倍,因为整个画布被 CSS 规则拉伸到更大的区域。
注意:如果未指定 width
和/或 height
的 CSS 规则,则浏览器将使用 HTML 属性来调整元素的大小,使这些值的 1 个单位等于页面上的 1px。如果未指定这些属性,则它们将默认为 300
的 width
和 150
的 height
。
【讨论】:
【参考方案4】:如果您在 CSS 中设置宽度和高度,画布将被拉伸。如果你想动态操作画布的尺寸,你必须像这样使用 JavaScript:
canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
【讨论】:
太棒了!感谢您的回答。我必须把canvas.setAttribute
放在canvas.getContext('2d')
之前以避免拉伸图像。【参考方案5】:
浏览器使用css的宽度和高度,但canvas元素根据canvas的宽度和高度进行缩放。在 javascript 中,读取 css 宽度和高度并将画布宽度和高度设置为该值。
var myCanvas = $('#TheMainCanvas');
myCanvas[0].width = myCanvas.width();
myCanvas[0].height = myCanvas.height();
【讨论】:
【参考方案6】:香尼玛修正
var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))
【讨论】:
【参考方案7】:CSS 设置画布元素的宽度和高度,因此它会影响坐标空间,使所有内容都倾斜
这是我如何使用 Vanilla JavaScript 设置宽度和高度的方法
canvas.width = numberForWidth
canvas.height = numberForHeight
【讨论】:
【参考方案8】:canvas 是通过缓冲区来渲染图像的,所以当你指定宽度和高度 html 属性时,缓冲区的大小和长度会发生变化,但是当你使用 css 时,缓冲区的大小是不变的。使图像拉伸。
使用 html 大小调整。
画布大小改变 -> 缓冲区大小改变 -> 渲染
使用 css 调整大小
画布大小改变 -> 渲染
由于缓冲区长度保持不变,当上下文渲染图像时, 图像显示在调整大小的画布中(但在未更改的缓冲区中呈现)。
【讨论】:
【参考方案9】:如果你想要一个基于例如的动态行为CSS 媒体查询,不要使用画布宽度和高度属性。使用 CSS 规则,然后在获取画布渲染上下文之前,为宽度和高度属性分配 CSS 宽度和高度样式:
var elem = document.getElementById("mycanvas");
elem.width = elem.style.width;
elem.height = elem.style.height;
var ctx1 = elem.getContext("2d");
...
【讨论】:
很明显,如果仅在 CSS 中指定尺寸,画布将获得默认坐标尺寸 (300 x 150)。但是,这个建议对我不起作用,但下面的解决方案可以。 @PerLindberg - 如果您为画布元素定义了 CSS 宽度和高度(以像素为单位),则此解决方案有效。以上是关于使用 CSS 时画布会被拉伸,但“宽度”/“高度”属性正常的主要内容,如果未能解决你的问题,请参考以下文章