簡體   English   中英

如何調整大小<canvas>基於窗口寬度/高度並保持縱橫比?

[英]How to resize <canvas> based on window width/height and maintain aspect ratio?

我想使用最大 1000px x 1000px 的畫布。 但如果屏幕更小,或者窗口變小,則在保持原始縱橫比的同時自動調整寬度/高度。 例如:如果寬度 = 500 像素,則畫布 = 500x500,而不是 500x1000。 如果高度 = 100,則畫布 = 100x100。 我不介意使用 javascript、css、html 來做到這一點。 謝謝你。

縮放以適應固定的縱橫比。

您可以使用CanvasRenderingContext2D.setTransform來縮放和定位變換以適合和居中內容。

您將需要一個參考分辨率來定義原始坐標比例1和方面。 例如...

const refRes = {width: 1000, height: 1000}; 

縮放以適合

然后,您可以計算比例和原點,以適應給定大小的畫布並將內容居中。 這是通過使用最小縮放維度來縮放內容來完成的。 例如...

// Get the scale to fit content to the canvas
const scale = Math.min(canvas.width / refRes.width, canvas.height / refRes.height);

// set the origin so that the scaled content is centered on the canvas
const origin = {
    x: (canvas.width - refRes.width * scale) / 2,
    y: (canvas.height - refRes.height * scale) / 2
};

// Set the transform to scale and center on canvas
ctx.setTransform(scale, 0, 0, scale, origin.x, origin.y);

// Then render your content using the original coordinates.
ctx.fillRect(0, 0, 1000, 1000); // will fit any sized canvas

由於這會保持外觀,因此根據畫布外觀,左右或上下可能會有未使用的像素。

縮放以填充

您可以縮放以填充,這將裁剪內容但確保使用所有像素。 只需使用最大縮放尺寸。 例如...

// Use max res to scale to fill
const scale = Math.max(canvas.width / refRes.width, canvas.height / refRes.height);

演示

演示顯示了縮放以適應大小隨機變化的畫布的內容。 內容在原始坐標系中呈現,2D 變換用於縮放以適應和居中。

 requestAnimationFrame(mainLoop); const ctx = canvas.getContext("2d"); const size = 1000; Math.TAU = Math.PI * 2; Math.randI = (m, M) => Math.random() * (M - m) + m | 0; // for unsigned int32 Math.nearZero = val => Math.abs(val) < 1e-3; const refRes = {width: size, height: size}; renderContent(); // State for canvas size changes var xRes = canvas.width, yRes = canvas.height; var xResC = xRes, yResC = yRes; // current resolution var xResD = 0, yResD = 0; // resolution delta change const rate = 0.2; // rate of canvas size change // WARNING there is no bounds checking for canvas size. // If rate < 0 || rate > 0.5 you MUST check that canvas size // is safe before setting its width and height function scaleToFit() { const scale = Math.min(canvas.width / refRes.width, canvas.height / refRes.height); ctx.setTransform( scale, 0, 0, scale, (canvas.width - refRes.width * scale) / 2, (canvas.height - refRes.height * scale) / 2 ); } function mainLoop() { xResC += (xResD = (xResD += (xRes - xResC) * rate) * rate); yResC += (yResD = (yResD += (yRes - yResC) * rate) * rate); const w = xResC | 0; const h = yResC | 0; if (w !== canvas.width || h !== canvas.height) { canvas.width = w; canvas.height = h; renderContent(); } if(Math.nearZero(xResD) && Math.nearZero(yResD)) { xRes = Math.randI(30, 300); yRes = Math.randI(30, 200); } requestAnimationFrame(mainLoop); } function renderContent() { scaleToFit(); ctx.fillStyle = "#Faa"; ctx.fillRect(0,0,size,size); ctx.fillStyle = "#8aF"; ctx.beginPath(); ctx.arc(size / 2, size / 2, size / 2 - 4, 0, Math.TAU); ctx.fill(); ctx.fillStyle = "#FF8"; ctx.fillRect( (size - size * Math.SQRT1_2) / 2, (size - size * Math.SQRT1_2) / 2, size * Math.SQRT1_2, size * Math.SQRT1_2 ); ctx.lineWidth = 10; ctx.beginPath(); ctx.arc(size / 2, size / 2, size / 2 - 4, 0, Math.TAU); ctx.rect( (size - size * Math.SQRT1_2) / 2, (size - size * Math.SQRT1_2) / 2, size * Math.SQRT1_2, size * Math.SQRT1_2 ); ctx.stroke(); }
 canvas { border: 1px solid black; }
 <canvas id="canvas"></canvas>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM