用于调整画布大小的 JavaScript 事件

问题描述 投票:0回答:6

更改画布的尺寸似乎会清除该画布上已完成的所有绘图。

是否有一个事件在画布调整大小时触发,以便我可以挂钩它并在发生时重绘?

javascript html canvas
6个回答
15
投票

2020 年更新

Jemenake 的答案看起来不错,但总的来说,我建议加载提供

debounce
功能的库,因为这就是所谓的。

例如,使用 lodash,您可以执行

window.addEventListner('resize', _.debounce(onResize, 500)
。请注意,还有第三个参数,您可以在其中指定所需的行为(例如
window.addEventListner('resize', _.debounce(onResize, 500, {leading: true, trailing true})
),尽管默认值应该相当不错。


Kit Sunde 的答案会在浏览器窗口不调整大小的情况下做很多不必要的工作。最好检查事件是否响应浏览器事件而调整大小,然后在给定的时间内忽略调整大小事件,然后再次进行检查(这将导致快速连续地进行两次检查,代码可能是进行了改进以防止这种情况发生,但您可能明白了)。

 (function(){
      var doCheck = true;
      var check = function(){
           //do the check here and call some external event function or something.
      };
      window.addEventListener("resize",function(){
           if(doCheck){
                check();
                doCheck = false;
                setTimeout(function(){
                     doCheck = true;
                     check();
                },500)
           }
      });
 })();

请注意,上面的代码是盲打的,没有经过检查。


13
投票

David Mulder 的答案是一个改进,但看起来它会在 first 调整大小事件后等待 timeout 毫秒后触发。换句话说,如果在超时之前发生更多大小调整,则不会重置计时器。我正在寻找相反的东西;我想要一些东西,它会等待一点时间让调整大小事件停止,然后在“最后一个”事件之后的一定时间后触发。下面的代码就是这样做的。 当前运行的任何定时器的 ID 将在timer_id 中。因此,每当调整大小时,它都会检查是否已经有时间运行。如果是这样,它会取消那个并开始一个新的。

function setResizeHandler(callback, timeout) { var timer_id = undefined; window.addEventListener("resize", function() { if(timer_id != undefined) { clearTimeout(timer_id); timer_id = undefined; } timer_id = setTimeout(function() { timer_id = undefined; callback(); }, timeout); }); } function callback() { // Here's where you fire-after-resize code goes. alert("Got called!"); } setResizeHandler(callback, 1500);



6
投票
窗户上有

)。我会每隔一段时间检查一次: function onResize( element, callback ){ var elementHeight = element.height, elementWidth = element.width; setInterval(function(){ if( element.height !== elementHeight || element.width !== elementWidth ){ elementHeight = element.height; elementWidth = element.width; callback(); } }, 300); } var element = document.getElementsByTagName("canvas")[0]; onResize( element, function(){ alert("Woo!"); } );



3
投票
Jemenake's

)之外,您是否尝试过ResizeObservercaniuse.com)? 例如:

const pleasantText = 'There is a handle! Let\'s try relaxing while resizing the awesome canvas! ->'; onResize = (entries) => { document.getElementsByTagName('span')[0].innerHTML = `${pleasantText} <b>${entries[0].target.offsetWidth}x${entries[0].target.offsetHeight}</b>`; }; const canvas = document.getElementsByTagName('canvas')[0]; const observer = new ResizeObserver(onResize); observer.observe(canvas);
* {
    overflow: hidden;
}

body > div:first-of-type {
    display: grid;
    place-items: center;
    width: 100vw;
    height: 100vh;
    user-select: none;
}

body > div:first-of-type div {
    display: grid;
    min-width: 12em;
    min-height: 6em;
    width: 16rem;
    height: 6rem;
    background: #ccc;
    overflow: auto;
    place-items: center;
    text-align: center;
    resize: both;
    grid-auto-columns: 20vw 1fr;
    grid-auto-flow: column;
    grid-gap: 20px;
    padding: 0.4rem 0.8rem;
    border-radius: 4px;
}

canvas {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    background: #ff9;
}
<div>
    <div>
        <span></span>
        <canvas></canvas>
    </div>
</div>


1
投票

function onresize() { // handle canvas resize event here } var _savedWidth = canvas.clientWidth; var _savedHeight = canvas.clientHeight; function isResized() { if(_savedWidth != canvas.clientWidth || _savedHeight != canvas.clientHeight) { _savedWidth = canvas.clientWidth; _savedHeight = canvas.clientHeight; onresize(); } } window.addEventListener("resize", isResized); (new MutationObserver(function(mutations) { if(mutations.length > 0) { isResized(); } })).observe(canvas, { attributes : true, attributeFilter : ['style'] });

    为了检测任何 JavaScript canvas.style 更改,MutationObserver API 非常适合。它不会检测特定的样式属性,但是 在这种情况下,检查 canvas.clientWidth 和 canvas.clientHeight 是否已更改就足够了。
  1. 如果画布大小在带有百分比单位的样式标签中声明,我们在使用 JavaScript 正确解释 css 选择器(>、*、::before、...)时会遇到问题。我认为在这种情况下最好的方法是设置一个 window.resize 处理程序并检查画布客户端大小。

-2
投票

var imgDat=ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height)

调整大小后

ctx.putImageData(imgDat,0,0)

© www.soinside.com 2019 - 2024. All rights reserved.