[英]JavaScript event for canvas resize
似乎更改 canvas 的尺寸会清除已在该 canvas 上完成的所有绘图。
是否有在 canvas resize 时触发的事件,所以我可以挂钩它并在它发生时重绘?
Jemenake 的答案看起来不错,但总的来说,我建议加载一个提供debounce
功能的库,因为这就是所谓的。
例如,使用 lodash 之一,您可以执行window.addEventListner('resize', _.debounce(onResize, 500)
。请注意,还有第三个参数可以指定您想要的行为(例如window.addEventListner('resize', _.debounce(onResize, 500, {leading: true, trailing true})
),虽然默认应该很好。
Kit Sunde 的回答会做很多不必要的工作,而浏览器 window 没有调整大小。 最好检查事件是否为响应浏览器事件而调整大小,然后在给定的时间内忽略调整大小事件,然后再次进行检查(这将导致快速连续进行两次检查,代码可能是改进以防止这种情况,但您可能会明白)。
(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)
}
});
})();
请注意,上面的代码是盲目输入的,没有经过检查。
David Mulder 的回答是一种改进,但看起来它会在第一次调整大小事件后等待超时毫秒后触发。 换句话说,如果在超时之前发生了更多的调整大小,它不会重置计时器。 我在寻找相反的东西; 我想要的东西会等待一点时间让调整大小事件停止,然后在最后一个事件之后的一定时间后触发。 下面的代码就是这样做的。
任何当前运行的计时器的 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);
您通常不想严格检查调整大小事件,因为当您进行动态调整大小时它们会触发很多,例如 jQuery 中的 $(window).resize 并且据我所知,元素上没有本机调整大小事件( window 上有)。 我会定期检查它:
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!"); } );
我没有找到任何内置事件来检测新的 canvas 尺寸,因此我试图找到两种情况的解决方法。
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 是否已更改就足够了。
如果 canvas 大小在带有百分比单位的样式标签中声明,我们在使用 Z686155AF75A60A0F6E9D80C1F7EDD3 正确解释 css 选择器(>、*、::before、...)时会遇到问题我认为在这种情况下,最好的方法是设置 window.resize 处理程序并检查 canvas 客户端大小。
除了Jemenake等其他答案中提到的去抖动逻辑之外,您是否尝试过ResizeObserver ( caniuse.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);
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>
将 canvas state 保存为 imageData,然后在调整大小后重新绘制
var imgDat=ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height)
调整大小后
ctx.putImageData(imgDat,0,0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.