使用 CSS 时画布会被拉伸,但使用“width”和“width”则正常。 “高度”属性

发布于 2024-08-27 17:51:58 字数 538 浏览 6 评论 0原文

我有 2 个画布,一个使用 HTML 属性 widthheight 来调整大小,另一个使用 CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 按其应有的方式显示,但 compteur2 不显示。内容是使用 JavaScript 在 300x300 画布上绘制的。

为什么会有显示差异?

替代文字

I have 2 canvases, one uses HTML attributes width and height to size it, the other uses CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 displays like it should, but not compteur2. The content is drawn using JavaScript on a 300x300 canvas.

Why is there a display difference?

alt text

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

绝情姑娘 2024-09-03 17:51:58

似乎 widthheight 属性决定了画布坐标系的宽度或高度,而 CSS 属性仅决定了显示它的框的大小。

HTML 规范对此进行了解释:

canvas 元素有两个属性来控制元素位图的大小:widthheight。这些属性在指定时必须具有有效的非负整数值。必须使用解析非负整数的规则来获取它们的数值。如果缺少某个属性,或者解析其值返回错误,则必须使用默认值。 width 属性默认为 300,height 属性默认为 150。

It seems that the width and height attributes determine the width or height of the canvas’s coordinate system, whereas the CSS properties just determine the size of the box in which it will be shown.

This is explained in the HTML specification:

The canvas element has two attributes to control the size of the element’s bitmap: width and height. These attributes, when specified, must have values that are valid non-negative integers. The rules for parsing non-negative integers must be used to obtain their numeric values. If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. The width attribute defaults to 300, and the height attribute defaults to 150.

我家小可爱 2024-09-03 17:51:58

要在画布上设置宽度高度,您可以使用:

canvasObject.setAttribute('width', '150');
canvasObject.setAttribute('height', '300');

To set the width and height on a canvas, you may use:

canvasObject.setAttribute('width', '150');
canvasObject.setAttribute('height', '300');
何止钟意 2024-09-03 17:51:58

对于 元素,widthheight 的 CSS 规则设置将绘制到页面的 canvas 元素的实际大小。另一方面,widthheight 的 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;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

两者都相对于画布元素的内部坐标绘制了相同的东西。但在第二个画布中,红色矩形的宽度将是原来的两倍,因为 CSS 规则将整个画布拉伸到更大的区域。

注意:如果未指定 width 和/或 height 的 CSS 规则,则浏览器将使用 HTML 属性来调整元素的大小,以使这些值的 1 个单位等于页面上 1 像素。如果未指定这些属性,则它们的宽度将默认为300高度150

For <canvas> elements, the CSS rules for width and height set the actual size of the canvas element that will be drawn to the page. On the other hand, the HTML attributes of width and height set the size of the coordinate system or 'grid' that the canvas API will use.

For example, consider this (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;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

Both have had the same thing drawn on them relative to the internal coordinates of the canvas element. But in the second canvas, the red rectangle will be twice as wide because the canvas as a whole is being stretched across a bigger area by the CSS rules.

Note: If the CSS rules for width and/or height aren't specified then the browser will use the HTML attributes to size the element such that 1 unit of these values equals 1px on the page. If these attributes aren't specified then they will default to a width of 300 and a height of 150.

余生共白头 2024-09-03 17:51:58

如果您在 CSS 中设置宽度和高度,画布将被拉伸。如果你想动态操纵画布的尺寸,你必须使用 JavaScript,如下所示:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');

The canvas will be stretched if you set the width and height in your CSS. If you want to dynamically manipulate the dimension of the canvas you have to use JavaScript like so:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
心如荒岛 2024-09-03 17:51:58

Shannimal校正

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))

Shannimal correction

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))
半窗疏影 2024-09-03 17:51:58

Canvas 通过缓冲区渲染图像,因此当您指定宽度和高度 HTML 属性时,缓冲区的大小和长度会发生变化,但当您使用 CSS 时,缓冲区的大小不会改变。使图像拉伸。

使用 HTML 调整大小。

画布尺寸已更改 ->缓冲区大小已更改 -> 渲染

使用 CSS 调整大小

画布的大小已更改 -> 由于缓冲区长度保持不变,所以

当上下文渲染图像时,
图像显示在调整大小的画布中(但在未更改的缓冲区中渲染)

Canvas renders image by buffer, so when you specify the width and height HTML attributes the buffer size and length changes, but when you use CSS, the buffer's size is unchanged. Making the image stretched.

Using HTML sizing.

Size of canvas is changed -> buffer size is changed -> rendered

Using CSS sizing

Size of canvas is changed -> rendered

Since the buffer length is kept unchanged, when the context renders the image,
the image is displayed in resized canvas (but rendered in unchanged buffer).

始终不够爱げ你 2024-09-03 17:51:58

CSS 设置画布元素的宽度和高度,因此它会影响坐标空间,使绘制的所有内容倾斜

这是我如何使用 Vanilla JavaScript 设置宽度和高度的方法

canvas.width = numberForWidth

canvas.height = numberForHeight

CSS sets the width and height of the canvas element so it affects the coordinate space leaving everything drawn skewed

Here's my way on how to set the width and height with Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
橙味迷妹 2024-09-03 17:51:58

如果您想要基于 CSS 媒体查询等动态行为,请不要使用画布宽度和高度属性。使用 CSS 规则,然后在获取画布渲染上下文之前,将 CSS 宽度和高度样式分配给宽度和高度属性:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...

If you want a dynamic behaviour based on, e.g. CSS media queries, don't use canvas width and height attributes. Use CSS rules and then, before getting the canvas rendering context, assign to width and height attributes the CSS width and height styles:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...
游魂 2024-09-03 17:51:58

我相信 CSS 有更好的机制来指定画布的大小,并且 CSS 必须决定样式,而不是 JavaScript 或 HTML。话虽如此,在 HTML 中设置宽度和高度对于解决画布问题非常重要。

CSS 有 !important 规则,允许覆盖其他样式属性的规则,包括 HTML 中的规则。通常,它的使用是不受欢迎的,但这里的使用是合法的黑客

在 WebAssembly 的 Rust 模块中,您可以执行以下操作:

fn update_buffer(canvas: &HtmlCanvasElement) {
    canvas.set_width(canvas.client_width() as u32);
    canvas.set_height(canvas.client_height() as u32);
}

//.. 
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
    // ...
    let canvas: Rc<_> = document
        .query_selector("canvas")
        .unwrap()
        .unwrap()
        .dyn_into::<HtmlCanvasElement>()
        .unwrap()
        .into();
    update_buffer(&canvas);
    // ...

    // create resizing handler for window
    {
        let on_resize = Closure::<dyn FnMut(_)>::new(move |_event: Event| {
            let canvas = canvas.clone();
            // ...

            update_buffer(&canvas);
            // ...
        window.add_event_listener_with_callback("resize", on_resize.as_ref().unchecked_ref())?;
        on_resize.forget();
    }
}

一旦加载 WASM 模块,然后每当调整窗口大小时,我们都会更新画布缓冲区。我们通过手动将画布的 widthheight 指定为 clientWidthclientHeight。也许有更好的方法来更新缓冲区,但我相信这个解决方案比 @SamB、@CoderNaveed、@Anthony Gedeon、@Bluerain、@Ben Jackson、@Manolo、@XaviGuardia、@Russel Harkins 和 @fermar 建议的解决方案更好因为

  1. 该元素是由 CSS 设计的,而不是 HTML。
  2. elem.style.width & 不同@Manolo 使用的 elem.style.height 技巧或 @XaviGuardia 使用的 JQuery 等效项,它将适用于尺寸由使用情况指定为 flex< 的 canvas 。 /code> 或 grid 项目。
  3. 与@Russel Harkings 的解决方案不同,这还可以处理调整大小。虽然我喜欢他的回答,因为它真的很干净、简单。
  4. WASM 是未来!哈哈:D.P.S

.有大量的 .unwrap() 因为 Rust 显式地处理可能的失败。

使用更好的库可以使PPS

    {
        let on_resize = Closure::<dyn FnMut(_)>::new(move |_event: Event| {
            let canvas = canvas.clone();
            // ...

            update_buffer(&canvas);
            // ...
        window.add_event_listener_with_callback("resize", on_resize.as_ref().unchecked_ref())?;
        on_resize.forget();
    }

变得更加干净。例如

add_resize_handler(&window, move |e: ResizeEvent| {
  let canvas = canvas.clone();
  // ...

  update_buffer(&canvas);
})

I believe CSS has much better machinery for specifying the size of the canvas and CSS must decide styling, not JavaScript or HTML. Having said that, setting width and height in HTML is important for working around the issue with canvas.

CSS has !important rule that allows to override other styling rules for the property, including those in HTML. Usually, its usage is frowned upon but here the use is a legitimate hack.

In Rust module for WebAssembly you can do the following:

fn update_buffer(canvas: &HtmlCanvasElement) {
    canvas.set_width(canvas.client_width() as u32);
    canvas.set_height(canvas.client_height() as u32);
}

//.. 
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
    // ...
    let canvas: Rc<_> = document
        .query_selector("canvas")
        .unwrap()
        .unwrap()
        .dyn_into::<HtmlCanvasElement>()
        .unwrap()
        .into();
    update_buffer(&canvas);
    // ...

    // create resizing handler for window
    {
        let on_resize = Closure::<dyn FnMut(_)>::new(move |_event: Event| {
            let canvas = canvas.clone();
            // ...

            update_buffer(&canvas);
            // ...
        window.add_event_listener_with_callback("resize", on_resize.as_ref().unchecked_ref())?;
        on_resize.forget();
    }
}

There we update the canvas buffer once the WASM module is loaded and then whenever the window is resized. We do it by manually specifying width and height of canvas as values of clientWidth and clientHeight. Maybe there are better ways to update the buffer but I believe this solution is better than those suggested by @SamB, @CoderNaveed, @Anthony Gedeon, @Bluerain, @Ben Jackson, @Manolo, @XaviGuardia, @Russel Harkins, and @fermar because

  1. The element is styled by CSS, not HTML.
  2. Unlike elem.style.width & elem.style.height trick used by @Manolo or its JQuery equivalent used by @XaviGuardia, it will work for canvas whose size is specified by usage as flex or grid item.
  3. Unlike the solution by @Russel Harkings, this also handles resizing. Though I like his answer because it is really clean and easy.
  4. WASM is the future! Haha :D

P.S. there's a ton of .unwrap() because Rust explicitly handles possible failures.

P.P.S.

    {
        let on_resize = Closure::<dyn FnMut(_)>::new(move |_event: Event| {
            let canvas = canvas.clone();
            // ...

            update_buffer(&canvas);
            // ...
        window.add_event_listener_with_callback("resize", on_resize.as_ref().unchecked_ref())?;
        on_resize.forget();
    }

can be done much cleaner with better libraries. E.g.

add_resize_handler(&window, move |e: ResizeEvent| {
  let canvas = canvas.clone();
  // ...

  update_buffer(&canvas);
})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文