当父元素更改其宽度/高度时,调整画布元素的大小

时间:2019-08-15 10:33:11

标签: javascript canvas

在我的应用程序中,我有一个div,其中包含一个显示图像的canvas元素。该应用程序还具有一个边栏,可以通过单击按钮将其隐藏,其他所有元素都应调整自身大小以占用剩余的空白空间。

这对于div和其他将宽度/高度设置为百分比的元素非常有效,但对于canvas元素则无效。

这是我的div:

<div id="background-img" class="image-div"></div>

.image-div {
  height: inherit;
  width: 100%;
  margin-top: 25px;
  position: absolute;
}

高度最初为305px,但在隐藏侧边栏时变为375px。

这是画布创建代码:

const imgDiv = document.getElementById('background-img');
if (imgDiv) {
  const blob = new Blob([svg], { type: 'image/svg+xml' });
  const url = URL.createObjectURL(blob);

  const canvas = document.createElement('canvas');
  canvas.className = 'canvas-background';
  canvas.id = 'canvas-id';
  const ctx = canvas.getContext('2d');

  canvas.width = imgDiv.clientWidth;
  canvas.height = imgDiv.clientHeight;

  const img = new Image();
  img.onload = function() {
    ctx.drawImage(img, 0, 0);
  };
  img.src = url;
  imgDiv.appendChild(canvas);
}

并且画布在任何地方都没有定义其他的CSS。

当父级更改画布的宽度和高度时,如何使画布自动调整大小(我尝试像在chrome中那样放大/缩小页面时也要使此调整大小有效例如,某些可与div或img元素一起使用的东西。

1 个答案:

答案 0 :(得分:1)

问题是还没有一个好的方法来做到这一点。本能地在元素上寻找resize事件。但这只能应用于explained here on MDNwindow

在进行了一些研究并查看了其他线程之后,我发现了几个可供您考虑的选项。

连续循环

使用递归函数绘制图像,该函数还将在每次绘制imgDiv时检查其宽度和高度。

CSS:

canvas {
    width: 100%;
    height: 100%;
}

JS:

function draw(ctx, imgDiv, img) {
    ctx.canvas.width = imgDiv.offsetWidth;
    ctx.canvas.height = imgDiv.offsetheight;
    ctx.drawImage(img, 0, 0);
    requestAnimationFrame(() => {
        draw(ctx, imgDiv, img);
    });
}

img.onload = function() {
    draw(ctx, imgDiv, img);
};

此选项的好处是可以一直检查,但是我认为它在性能方面可能很繁琐。 requestAnimationFrame仅在帧速率速度允许的情况下才通过触发功能来提高性能。所以平均每秒大约60次。

ResizeObserver(警告:实验技术)

这是我还没有见过的那个。 ResizeObserver是新的,属于IntersectionObserverPerformanceObserverMutationObserver的家族。顾名思义,它可以观察到更改后的元素的大小,并在检测到更改时触发回调。

它是这样的:

const observer = new ResizeObserver(entries => {
    entries.forEach(entry => {
        // Update the canvas dimensions. 
    });
});

// Observer the image-div when it resizes.
observer.observe(imgDiv);

由于它是实验性的,因此我不建议您使用它,尽管它完全适合您的情况。 Caniuse上有更多关于浏览器对此API的支持,以及Alligator.io上有关如何使用它的文章。

resize上使用window事件

这只会捕获更改窗口或文档的宽度的情况。而且,如果您打开和关闭侧边栏,则需要进行一些额外的修改。

window.addEventListener('resize', (event) => {
    requestAnimationFrame(() => {
        // Update the canvas dimensions. 
    });
});

建议在此处使用requestAnimationFrame,因为resize事件将在每个像素上调用,并且会降低性能。

编辑:

看来Artyomska已经解决了这个问题。而且,尽管该问题已解决,但我仍然想分享我的研究,以防将来对该线程进行查询。