簡體   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