【问题标题】:Update HTML canvas width and height attributes automatically自动更新 HTML 画布的宽度和高度属性
【发布时间】:2015-05-28 20:30:26
【问题描述】:

我想将 HTML5 画布与 flexbox 一起使用。当用户调整窗口大小时,我需要自动设置 canvas.width 和 canvas.height。我已经尝试使用 jQuery:

$(".cnvs").attr("width", $(".cnvs").width());
$(".cnvs").attr("height", $(".cnvs").height());

但它会不断增加画布的实际宽度,因此它几乎填满了整个屏幕。我已经输入了it on jsfiddle - 尝试使用分隔符调整输出窗口的大小。

有什么合理的方法吗?谢谢。

编辑:明确一点:我不想用该画布填满整个屏幕。我想要 UI:

<div class="container">
   <div class="control"></div>
   <canvas></canvas>
   <div class="control"></div>
</div>

然后使用 flexbox 将这三个元素并排放置,而 canvas 将是另一个元素的两倍宽。这没有问题,但 canvas.width 和 canvas.height 没有得到更新,所以每当我在画布上渲染一些东西时,它都会被渲染为画布是 320x140 像素。

编辑2:很抱歉,但是(可能是因为我的英语不好)我不够清楚。我会再解释一遍:

只有使用 flexbox,canvas 元素的实际宽度才是正确的(即使不使用任何 JavaScript 代码)。我的问题是,虽然宽度是正确的(并且$(".cnvs").width() 返回正确的宽度值),但它没有任何“宽度”属性,它仍然是:

<canvas>
</canvas>

而且我需要自己提供宽度参数(因为它在未设置时渲染很糟糕)。当我尝试使用我的代码或建议时:

...
var rect = canvas.parentNode.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
...

它的行为很奇怪,画布的宽度随着每次调整大小而不断增加,但太多了(它几乎立即删除了两个控制 div)。

【问题讨论】:

    标签: javascript jquery html css canvas


    【解决方案1】:

    更新 2

    如果我对问题的理解正确:画布有一个 flex CSS 集(目前未在问题中显示)。它将画布定义为其他两个元素大小的 2 倍,但由于画布是调整大小而不是它的位图,所以绘图也是拉伸的,您希望位图动态采用。

    如果是这样,请对代码进行此更改 -

    此更新将单独保留画布 元素 的 CSS 规则,让 flexbox 处理它。它将读取元素的实际像素大小,然后将其应用于位图,这样数据就不会被拉伸:

    $(window).on("resize", function() {
      var cnvs = $(".cnvs")[0];                  // cache canvas element
      var rect = cnvs.getBoundingClientRect();   // actual size of canvas el. itself
    
      cnvs.width = rect.width;
      cnvs.height = rect.height;
      // ... redraw content here ...
    }
    

    此外,由于调整窗口大小会产生很多事件,您可能需要考虑“去抖动”,以便只处理最近的调整大小:

    var timerID;
    $(window).on("resize", function() {
      clearTimeout(timerID);
      timerID = setTimeout(function() {
        var cnvs = $(".cnvs")[0];                  // cache canvas element
        var rect = cnvs.getBoundingClientRect();   // actual size of canvas el. itself
    
        cnvs.width = rect.width;
        cnvs.height = rect.height;
        // ... redraw content here ...
      }, 180);  // adjust at will
    }
    

    这会将调整大小/重绘延迟到 180 毫秒。

    【讨论】:

    • 不,这不起作用。我不想用我的画布填满整个屏幕 - 我希望我的画布的实际宽度和高度由 flexbox 设置,然后将宽度和高度属性设置为正确的值。
    • 好的,我发现这也不起作用 - 它还填满了整个屏幕。我认为这是因为画布的父节点填满了整个屏幕所以我把它放到另一个 div 中(所以我有全角 div 和 display: flex; 和三个 div 里面,第二个里面是画布)但它一直在做它做的事情之前。
    • @GarretRaziel 等待...画布的 css 设置正确,使用 flexbox 使其大小成为另一个的 2 倍。您希望画布的 位图 然后更新,而不是画布元素..? (你能分享一下画布的css和设置吗?)
    • 是的,这就是问题所在。我不想在这里发布所有 HTML、JS 和 CSS,所以我把它放在 jsfiddle 上:jsfiddle.net/h4hthyck/2 - 这是你提出的解决方案,如果你尝试在 JavaScript 屏幕和输出屏幕之间使用分隔符,它的行为会很混乱.
    • @GarretRaziel 我使用 flex-grow 这意味着元素只会增大,不会缩小。看看this 看看是否可以使用可选设置。
    【解决方案2】:

    你甚至不用加载 jQuery,很简单:

    var canvas = document.querySelector("canvas");
    
    window.addEventListener("resize", function(){
      canvas.setAttribute("width", window.innerWidth);
      canvas.setAttribute("height", window.innerHeight)
    })
    

    【讨论】:

      【解决方案3】:

      您必须为窗口对象的调整大小事件添加一个侦听器。 如果您正在寻找 jquery 解决方案。

      $( window ).resize(function() {
         $(".cnvs").attr("width", $(window).width());
         $(".cnvs").attr("height", $(window).height());
      });
      

      这应该可以正常工作。

      【讨论】:

      • 对不起,这只是一个 sn-p。我在我的代码或 jsfiddle 中都有这种方式。
      • 没问题,K3N的解决方案其实是最好的,如果能解决你的问题,你应该接受。
      猜你喜欢
      • 1970-01-01
      • 2017-03-13
      • 1970-01-01
      • 2020-09-12
      • 2016-04-17
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多