繁体   English   中英

将 canvas 调整为视口而不损失质量

[英]Resize canvas to viewport without loosing quality

每当用户调整浏览器 window 的大小时,我都试图让 canvas 填充整个视口并调整大小。 但是,当我尝试使用100%的大小时,它会降低质量。

我是 JavaScript 编程的新手。

有人可以帮帮我吗?

我想出了一个办法:

我计算一个缩放因子,通过它我缩放大小,但不是每个绘制元素的 position。 我不想缩放 position,因为这样一些元素可能会不在屏幕上。 因此,正如评论中所建议的,我不能使用setTransform 这是我用于计算比例因子的代码。 如果有人有改进,请在下面的评论中分享!

if (window.screen.width > window.screen.height)
    scalingFactor = window.screen.width * window.devicePixelRatio / 1280;
else
    scalingFactor = window.screen.height * window.devicePixelRatio / 720;

在丢失当前数据的情况下调整 canvas 大小的最简单方法是存储数据,然后调整 canvas 的大小(将其清除),然后将数据重新绘制到 ZFCC790C72A86190DE1ZB549D0DDC6F55C 中。 看起来像这样:

const data = ctx.getImageData( 0, 0, canvas.width, canvas.height );
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.putImageData( data, 0, 0 );

在最纯粹、最简单的例子中,它看起来像这样:

 /* This method does the resize by storing the data and redrawing it. It loses any data outside of the screen, though. */ function onResize( event ){ const data = ctx.getImageData( 0, 0, canvas.width, canvas.height ); canvas.width = innerWidth; canvas.height = innerHeight; ctx.putImageData( data, 0, 0 ); } /* This method is for drawing some content to help visualisation. */ function onRedraw(){ const r = v => Math.floor(Math.random() * v); canvas.width = innerWidth; canvas.height = innerHeight; ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth, innerHeight ); ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth / 2, innerHeight / 2 ); ctx.fillRect( innerWidth / 2, innerHeight / 2, innerWidth / 2, innerHeight / 2 ); } window.addEventListener( 'resize', onResize ); const canvas = document.createElement( 'canvas' ); const ctx = canvas.getContext( '2d' ); const reset = document.getElementById( 'reset' ); document.body.appendChild( canvas ); onRedraw(); redraw.addEventListener( 'click', onRedraw );
 body { padding: 0; margin: 0; overflow: hidden; } button { position: fixed; top: 20px; left: 20px; z-index: 1; }
 <button id="redraw">Redraw</button>

但是,当您的 window 增长和收缩时,您会丢失在 canvas 之外绘制的数据,因为数据永远不会保存。 我们可以用我们的图形保存一个缓冲区,这可以简化一些事情,但会使代码稍微复杂一些。 在这种情况下,我们可以使用第二个 canvas 来保存我们之前绘制的所有最大屏幕数据,仅供参考:

 /* This method does the resize by storing the data and redrawing it. It retains data outside the screen in a buffer that holds the maximum size ever drawn. */ function onResize( event ){ const data = bufferCtx.getImageData( 0, 0, bufferCanvas.width, bufferCanvas.height ); bufferCanvas.width = Math.max( bufferCanvas.width, innerWidth ); bufferCanvas.height = Math.max( bufferCanvas.height, innerHeight ); bufferCtx.putImageData( data, 0, 0 ); bufferCtx.drawImage( canvas, 0, 0 ); canvas.width = innerWidth; canvas.height = innerHeight; ctx.drawImage( bufferCanvas, 0, 0 ); } /* This method is for drawing some content to help visualisation. */ function onRedraw(){ const r = v => Math.floor(Math.random() * v); canvas.width = innerWidth; canvas.height = innerHeight; ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth, innerHeight ); ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth / 2, innerHeight / 2 ); ctx.fillRect( innerWidth / 2, innerHeight / 2, innerWidth / 2, innerHeight / 2 ); } window.addEventListener( 'resize', onResize ); const canvas = document.createElement( 'canvas' ); const ctx = canvas.getContext( '2d' ); const bufferCanvas = document.createElement( 'canvas' ); const bufferCtx = bufferCanvas.getContext( '2d' ); const reset = document.getElementById( 'reset' ); document.body.appendChild( canvas ); onRedraw(); redraw.addEventListener( 'click', onRedraw );
 body { padding: 0; margin: 0; overflow: hidden; } button { position: fixed; top: 20px; left: 20px; z-index: 1; }
 <button id="redraw">Redraw</button>

如果您宁愿使用完全不丢失数据并“重新调整” canvas 最好,也许最好使用这样的东西:

 /* This method does the resize by just redrawing the canvas from a buffer: */ function onResize( event ){ bufferCanvas.width = canvas.width; bufferCanvas.height = canvas.height; bufferCtx.drawImage( canvas, 0, 0 ); canvas.width = innerWidth; canvas.height = innerHeight; ctx.drawImage( bufferCanvas, 0, 0, canvas.width, canvas.height ); } /* This method is for drawing some content to help visualisation. */ function onRedraw(){ const r = v => Math.floor(Math.random() * v); canvas.width = innerWidth; canvas.height = innerHeight; ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth, innerHeight ); ctx.fillStyle = `rgb(${r(255)},${r(255)},${r(255)})`; ctx.fillRect( 0, 0, innerWidth / 2, innerHeight / 2 ); ctx.fillRect( innerWidth / 2, innerHeight / 2, innerWidth / 2, innerHeight / 2 ); } window.addEventListener( 'resize', onResize ); const canvas = document.createElement( 'canvas' ); const ctx = canvas.getContext( '2d' ); const bufferCanvas = document.createElement( 'canvas' ); const bufferCtx = bufferCanvas.getContext( '2d' ); const reset = document.getElementById( 'reset' ); document.body.appendChild( canvas ); onRedraw(); redraw.addEventListener( 'click', onRedraw );
 body { padding: 0; margin: 0; overflow: hidden; } button { position: fixed; top: 20px; left: 20px; z-index: 1; }
 <button id="redraw">Redraw</button>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM