HTML5 缩放 canvas 以适合页面但保持 canvas 图像为特定尺寸
HTML5 scale canvas to fit page but keep canvas image at specific size
我正在创建 1200W x 300H 的特定尺寸图像,完成后我将图像传回我的服务器。我有所有的工作。
但是,在创建图像时,1200x300 的尺寸让许多用户无法使用页面 - 尤其是在移动设备上。有没有我可以使用的方法可以创建特定 1200x300 的图像,然后以较小的比例直观地显示图像以适合屏幕?
目前我能做的最好的事情是使用 DIV 和 overflow:hidden
来保持 DIV 在页面上的正确大小,但这不会缩放实际图像吃下。事实上,图像大多偏离中心,只能在屏幕上看到图像的左侧部分。
<div style="overflow:hidden;" >
<canvas id="canvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>
如果我缩小 canvas 以适合页面,则创建的图像尺寸较小,而不是我需要传回服务器的尺寸。
可以这样做吗?
=============更新================
<div style="overflow:hidden;" >
<canvas id="displayCanvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
<canvas id="realCanvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>
#CSS
#realCanvas {
width:100vw;
height: 25vw ;
}
#JS
function buildBanner () {
Debugger.log("Drawing Canvas");
if(!canvasSupport()) {
return;
}
var wCanvas = 1200 ;
var hCanvas = 300 ;
var wImg = 400 ;
var hImg = 100 ;
var hRatio = wCanvas / wImg ;
var vRatio = hCanvas / hImg ;
var ratio = Math.min ( hRatio, vRatio );
var centerShift_x = ( wCanvas - wImg*ratio ) / 2;
var centerShift_y = ( hCanvas - hImg*ratio ) / 2;
var displayCanvas = document.getElementById('displayCanvas') ;
var displayContext = displayCanvas.getContext('2d');
var realCanvas = document.getElementById('realCanvas');
var realContext = realCanvas.getContext('2d');
var text1 = document.getElementById('textType1') ;
var text2 = document.getElementById('textType2') ;
if (text1.checked) {
var bannerText = document.getElementById('cVendor').value ;
console.log("Text1: "+ bannerText) ;
} else if (text2.checked) {
var bannerText = document.getElementById('cVendorName').value ;
console.log("Text2: "+ bannerText) ;
}
var textStrokeColor = "#000000";
var textBaseline = "middle";
var textAlign = "center";
// This is the event handler for listening for a key up event in the text box form
// It will call the textBoxChanged function to update the text in the canvas
var fontSize = document.getElementById("fontSize").value;
var fontFaceSelect = document.getElementById("fontFace");
var fontFace = fontFaceSelect.options[fontFaceSelect.selectedIndex].value ;
var fontWeightSelect = document.getElementById("fontWeight");
var fontWeight = fontWeightSelect.options[fontWeightSelect.selectedIndex].value ;
var fontStyleSelect = document.getElementById("fontStyle");
var fontStyle = fontStyleSelect.options[fontStyleSelect.selectedIndex].value ;
var fillTypeSelect = document.getElementById("fillType");
var fillType = fillTypeSelect.options[fillTypeSelect.selectedIndex].value ;
var strokeTypeSelect = document.getElementById("strokeType");
var strokeType = strokeTypeSelect.options[strokeTypeSelect.selectedIndex].value ;
var textFillColor = document.getElementById("textFillColor").value ;
var bgFillColor = document.getElementById("bgFillColor").value ;
var imageData = document.getElementById("createImageData");
realContext = drawScreen(realContext,wCanvas,hCanvas,4);
displayContext = drawScreen(displayContext,wImg,hImg,1) ;
var imageDataDisplay = document.getElementById("imageDataDisplay");
imageDataDisplay.value = realCanvas.toDataURL();
function drawScreen(thisContext,x,y,xSize) {
thisContext.clearRect(0, 0, x, y);
var metrics = thisContext.measureText(bannerText);
var textWidth = metrics.width;
var xPosition = x / 2
var yPosition = y / 2;
// Draws the Text Box
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
// Draws the actual text
var xFontSize = fontSize * xSize ;
thisContext.font = fontWeight + " " + fontStyle + " " + xFontSize + "px " + fontFace;
thisContext.textBaseline = textBaseline;
thisContext.textAlign = textAlign;
var tempColor;
switch(fillType) {
case "colorFill":
Debugger.log("Color Fill");
tempColor = textFillColor;
break;
case "linearGradient":
Debugger.log("Linear Gradient");
var linGradient = thisContext.createLinearGradient(xPosition-textWidth/2, yPosition, xPosition+textWidth/2, yPosition);
linGradient.addColorStop(0, textFillColor);
tempColor = linGradient;
break;
case "radialGradient":
Debugger.log("Radial Gradient");
var radGradient = thisContext.createRadialGradient(xPosition, yPosition, 1, xPosition, yPosition, textWidth/2);
radGradient.addColorStop(0, textFillColor);
tempColor = radGradient;
break;
}
switch(strokeType) {
case "fill":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
break;
case "stroke":
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
case "both":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
}
return thisContext ;
}
}
这可以通过侦听 resize
事件并相应地操纵 CSS 宽度和高度属性来完成,但是如果您的 <canvas>
元素始终具有相同的大小,则有更简单的方法.
要了解发生了什么,您需要知道通过 canvas' 元素自身属性设置的宽度和高度是 canvas 的 'real' 分辨率。 CSS 宽度和高度属性可以控制屏幕上实际呈现的尺寸。
我们想要做的是缩放 canvas 以填充浏览器的可用垂直视口 和 缩放它的高度,同时保持 canvas' 的原始纵横比比例。
首先我们需要计算它的纵横比:300 / 1200 = 0.25
这意味着它的高度是它的宽度的 1/4。用简单的英语来说,我们希望 canvas 宽度为视口宽度的 100%,高度为视口宽度的 25%。
幸运的是,这直接转移到 CSS vw
单元。例如100vw==100% viewport width
.
所以你所要做的就是将 canvas CSS 宽度设置为 100vw
并将其高度设置为 25vw
.
这是一个例子:
let image = new Image();
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
image.crossOrigin = 'anonymous';
image.onload = (e) => {
context.drawImage(e.target, 0, 0, canvas.width, canvas.height);
}
image.src = 'https://picsum.photos/id/10/1200/300';
#canvas {
background-color: black;
width: 100vw;
height: 25vw;
}
<div style="overflow:hidden;">
<canvas id="canvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>
我正在创建 1200W x 300H 的特定尺寸图像,完成后我将图像传回我的服务器。我有所有的工作。
但是,在创建图像时,1200x300 的尺寸让许多用户无法使用页面 - 尤其是在移动设备上。有没有我可以使用的方法可以创建特定 1200x300 的图像,然后以较小的比例直观地显示图像以适合屏幕?
目前我能做的最好的事情是使用 DIV 和 overflow:hidden
来保持 DIV 在页面上的正确大小,但这不会缩放实际图像吃下。事实上,图像大多偏离中心,只能在屏幕上看到图像的左侧部分。
<div style="overflow:hidden;" >
<canvas id="canvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>
如果我缩小 canvas 以适合页面,则创建的图像尺寸较小,而不是我需要传回服务器的尺寸。
可以这样做吗?
=============更新================
<div style="overflow:hidden;" >
<canvas id="displayCanvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
<canvas id="realCanvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>
#CSS
#realCanvas {
width:100vw;
height: 25vw ;
}
#JS
function buildBanner () {
Debugger.log("Drawing Canvas");
if(!canvasSupport()) {
return;
}
var wCanvas = 1200 ;
var hCanvas = 300 ;
var wImg = 400 ;
var hImg = 100 ;
var hRatio = wCanvas / wImg ;
var vRatio = hCanvas / hImg ;
var ratio = Math.min ( hRatio, vRatio );
var centerShift_x = ( wCanvas - wImg*ratio ) / 2;
var centerShift_y = ( hCanvas - hImg*ratio ) / 2;
var displayCanvas = document.getElementById('displayCanvas') ;
var displayContext = displayCanvas.getContext('2d');
var realCanvas = document.getElementById('realCanvas');
var realContext = realCanvas.getContext('2d');
var text1 = document.getElementById('textType1') ;
var text2 = document.getElementById('textType2') ;
if (text1.checked) {
var bannerText = document.getElementById('cVendor').value ;
console.log("Text1: "+ bannerText) ;
} else if (text2.checked) {
var bannerText = document.getElementById('cVendorName').value ;
console.log("Text2: "+ bannerText) ;
}
var textStrokeColor = "#000000";
var textBaseline = "middle";
var textAlign = "center";
// This is the event handler for listening for a key up event in the text box form
// It will call the textBoxChanged function to update the text in the canvas
var fontSize = document.getElementById("fontSize").value;
var fontFaceSelect = document.getElementById("fontFace");
var fontFace = fontFaceSelect.options[fontFaceSelect.selectedIndex].value ;
var fontWeightSelect = document.getElementById("fontWeight");
var fontWeight = fontWeightSelect.options[fontWeightSelect.selectedIndex].value ;
var fontStyleSelect = document.getElementById("fontStyle");
var fontStyle = fontStyleSelect.options[fontStyleSelect.selectedIndex].value ;
var fillTypeSelect = document.getElementById("fillType");
var fillType = fillTypeSelect.options[fillTypeSelect.selectedIndex].value ;
var strokeTypeSelect = document.getElementById("strokeType");
var strokeType = strokeTypeSelect.options[strokeTypeSelect.selectedIndex].value ;
var textFillColor = document.getElementById("textFillColor").value ;
var bgFillColor = document.getElementById("bgFillColor").value ;
var imageData = document.getElementById("createImageData");
realContext = drawScreen(realContext,wCanvas,hCanvas,4);
displayContext = drawScreen(displayContext,wImg,hImg,1) ;
var imageDataDisplay = document.getElementById("imageDataDisplay");
imageDataDisplay.value = realCanvas.toDataURL();
function drawScreen(thisContext,x,y,xSize) {
thisContext.clearRect(0, 0, x, y);
var metrics = thisContext.measureText(bannerText);
var textWidth = metrics.width;
var xPosition = x / 2
var yPosition = y / 2;
// Draws the Text Box
thisContext.globalAlpha = 1.0;
thisContext.fillStyle = bgFillColor ;
thisContext.fillRect(0,0,x,y);
// Draws the actual text
var xFontSize = fontSize * xSize ;
thisContext.font = fontWeight + " " + fontStyle + " " + xFontSize + "px " + fontFace;
thisContext.textBaseline = textBaseline;
thisContext.textAlign = textAlign;
var tempColor;
switch(fillType) {
case "colorFill":
Debugger.log("Color Fill");
tempColor = textFillColor;
break;
case "linearGradient":
Debugger.log("Linear Gradient");
var linGradient = thisContext.createLinearGradient(xPosition-textWidth/2, yPosition, xPosition+textWidth/2, yPosition);
linGradient.addColorStop(0, textFillColor);
tempColor = linGradient;
break;
case "radialGradient":
Debugger.log("Radial Gradient");
var radGradient = thisContext.createRadialGradient(xPosition, yPosition, 1, xPosition, yPosition, textWidth/2);
radGradient.addColorStop(0, textFillColor);
tempColor = radGradient;
break;
}
switch(strokeType) {
case "fill":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
break;
case "stroke":
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
case "both":
thisContext.fillStyle = tempColor;
thisContext.fillText(bannerText, xPosition, yPosition);
thisContext.strokeStyle = textStrokeColor;
thisContext.strokeText(bannerText, xPosition, yPosition);
break;
}
return thisContext ;
}
}
这可以通过侦听 resize
事件并相应地操纵 CSS 宽度和高度属性来完成,但是如果您的 <canvas>
元素始终具有相同的大小,则有更简单的方法.
要了解发生了什么,您需要知道通过 canvas' 元素自身属性设置的宽度和高度是 canvas 的 'real' 分辨率。 CSS 宽度和高度属性可以控制屏幕上实际呈现的尺寸。
我们想要做的是缩放 canvas 以填充浏览器的可用垂直视口 和 缩放它的高度,同时保持 canvas' 的原始纵横比比例。
首先我们需要计算它的纵横比:300 / 1200 = 0.25
这意味着它的高度是它的宽度的 1/4。用简单的英语来说,我们希望 canvas 宽度为视口宽度的 100%,高度为视口宽度的 25%。
幸运的是,这直接转移到 CSS vw
单元。例如100vw==100% viewport width
.
所以你所要做的就是将 canvas CSS 宽度设置为 100vw
并将其高度设置为 25vw
.
这是一个例子:
let image = new Image();
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
image.crossOrigin = 'anonymous';
image.onload = (e) => {
context.drawImage(e.target, 0, 0, canvas.width, canvas.height);
}
image.src = 'https://picsum.photos/id/10/1200/300';
#canvas {
background-color: black;
width: 100vw;
height: 25vw;
}
<div style="overflow:hidden;">
<canvas id="canvas" width="1200" height="300">
Your browser does not support Canvas.
</canvas>
</div>