javascript 基于画布大小的 HTML5 画布字体大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22943186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 00:03:57  来源:igfitidea点击:

HTML5 Canvas Font Size Based on Canvas Size

javascripthtmlcanvas

提问by Nathan McKaskle

I have the canvas size set to 1/3 the window.innerHeight and window.innerWidth of the browser.

我将画布大小设置为浏览器的 window.innerHeight 和 window.innerWidth 的 1/3。

Most of the elements on the canvas are also set based on the width and height of the canvas, so that they scale down in size and are positioned based on the size of the canvas.

画布上的大多数元素也是根据画布的宽度和高度设置的,因此它们按比例缩小并根据画布的大小进行定位。

How do I scale font sizes based on this as well?

我如何基于此缩放字体大小?

For example, the font size of my opening screen of a game I'm making, is 80pt. That's way too big if the browser is really small. It goes off the canvas.

例如,我正在制作的游戏的打开屏幕的字体大小是 80pt。如果浏览器真的很小,那就太大了。它脱离了画布。

回答by

Simply scale the font-sizewith a factor.

简单地font-size用一个因子来缩放。

The basis

基础

Lets say your canvas default size is 1000pixels and the font size is 80pixels (canvas converts pt to pixels - I use 80here for simplicity, see bottom).

假设您的画布默认大小是1000像素,字体大小是80像素(画布将 pt 转换为像素 -80为了简单起见,我在这里使用,见底部)。

Snap

折断

That will create a relationship of:

这将创建以下关系:

ratio = 80 / 1000 = 0.08

Lets verify when canvas width is 1000 by multiply with that ratio:

让我们通过乘以该比率来验证画布宽度何时为 1000:

fontSize = 1000 * ratio = 80;

And we see we have 80 for the font as expected.

我们看到我们有 80 个字体。

Now that the canvas size is smaller, lets say 500 pixels:

现在画布尺寸变小了,假设为 500 像素:

fontSize = 500 * ratio = 40;

That should correspond about to the relationship. Note that fonts do not behave linearly like that but it will be approximately correct.

那应该对应于关系。请注意,字体不会像那样线性地表现,但它会大致正确。

Now simply set the size of the font:

现在只需设置字体的大小:

ctx.font = (fontSize|0) + 'px myFont';

Solution

解决方案

The final code from this is in essence very simple:

最终的代码本质上非常简单:

var fontBase = 1000,                   // selected default width for canvas
    fontSize = 70;                     // default size for font

function getFont() {
    var ratio = fontSize / fontBase;   // calc ratio
    var size = canvas.width * ratio;   // get font size based on current width
    return (size|0) + 'px sans-serif'; // set font
}

Every time you need to update the font (ie. resize) just call:

每次需要更新字体(即调整大小)时,只需调用:

ctx.font = getFont();                  // call getFont to set new font size

The default values are snapshot of whatever size works in the moment/during development.

默认值是当前/开发过程中任何大小的快照。

Live demo

现场演示

To convert point to pixel size you simply use system DPI / 72:

要将点转换为像素大小,您只需使用 system DPI / 72

80 pt * (96 / 72) = 107 pixels @ 96 DPI.

回答by markE

Many responsive designs use media breakpoints to control font sizes.

许多响应式设计使用媒体断点来控制字体大小。

The font size remains fixed through a range of media sizes.

字体大小在一系列媒体大小中保持固定。

In your resize event handler, apply a font size to a range of canvas sizes:

在您的 resize 事件处理程序中,将字体大小应用于一系列画布大小:

if(canvas.width<480){
    context.font='14px verdana';
}else if(canvas.width<768){
    context.font='30px verdana';
}else{
    context.font='80px verdana';
}

[ And more efficiently... ]

[ 并且更有效... ]

Predefine some font sizes for each media format:

为每种媒体格式预定义一些字体大小:

var fontSizes={
    phone:{
        XSmall:6,
        Small:8,
        Medium:10,
        Large:12,
        XLarge:14
    },
    tablet:{
        XSmall:10,
        Small:12,
        Medium:16,
        Large:24,
        XLarge:30
    },
    desktop:{
        XSmall:14,
        Small:18,
        Medium:30,
        Large:40,
        XLarge:80
    },
}

You can use these predefined font sizes for your canvas text:

您可以为画布文本使用这些预定义的字体大小:

context.font=fontSizes[media].XSmall+" verdana";
context.fillText("XSmall text",20,20);

context.font=fontSizes[media].Large+" verdana";
context.fillText("Large text",20,20);

Then in your resize handler, you just have to set the appropriate media type.

然后在您的调整大小处理程序中,您只需设置适当的媒体类型。

This way you don't need to recode context.fonteverywhere in your project.

这样你就不需要context.font在项目的任何地方重新编码。

var media="desktop";

if(canvas.width<480){
    media="phone";
}else if(canvas.width<768){
    media="tablet";
}else{
    media="desktop";
}

回答by GameAlchemist

You should think your coordinates as virtual coordinates : if the canvas takes 1/3 of the screen, ask your self : how much room (relative) should the font take, not its size.

您应该将您的坐标视为虚拟坐标:如果画布占屏幕的 1/3,请问您自己:字体应占用多少空间(相对),而不是其大小。

Decide once and for all of a virtual resolution of your canvas, then draw draw everything in that resolution... provided you scaled the canvas before.

一劳永逸地确定画布的虚拟分辨率,然后以该分辨率绘制所有内容……前提是您之前缩放了画布。

For instance you could decide your canvas has a 600 x 200virtual resolution. When you know the real window size, you'll have the real canvas size. Then scale the canvas with scale(realWidth/600, realHeight/200), and all will look the same on all devices.

例如,您可以决定您的画布具有600 x 200虚拟分辨率。当您知道真实的窗口大小时,您将拥有真实的画布大小。然后用 缩放画布scale(realWidth/600, realHeight/200),在所有设备上看起来都一样。

I just made a small fiddle to illustrate, you will see that it generates the 'same' image for very differently sized canvas :
http://jsbin.com/tisoguve/1/edit?js,output

我只是做了一个小小提琴来说明,你会看到它为非常不同大小的画布生成“相同”的图像:http:
//jsbin.com/tisoguve/1/edit?js,output

enter image description here

在此处输入图片说明

回答by John Hood

I do not like using a determined width or height for any application. Instead, I use the window object to determine the amount of space on the screen instead of saying "width=1000" it would look more like the code below. I take note of the current screen resolution I am using so that when adjusting content size on the screen everything scales as it should based on the size when it was created. Assuming that the original screen resolution is 1366 and we want the original font set at 20 .....

我不喜欢为任何应用程序使用确定的宽度或高度。相反,我使用 window 对象来确定屏幕上的空间量,而不是说“width=1000”,它看起来更像下面的代码。我记下我正在使用的当前屏幕分辨率,以便在调整屏幕上的内容大小时,一切都会根据创建时的大小进行缩放。假设原始屏幕分辨率为 1366 并且我们希望原始字体设置为 20 .....

<canvas id="canvas"" width="0" height="0" style="position:relative;" ></canvas>
var canvas = document.getElementById("canvas");
var context= canvas.getContext('2d');
var canvas.width = document.body.clientWidth;
var canvas.height = document.body.clientHeight;
var px= 20-(((1366-canvas.width)/1366)*20); 
var fontStyle = "italic";
var fontWeight = "bold";
var fontSize = +px+"px";
var fontFamily = "Verdana";
var b = " ";
context.font = fontStyle + b + fontWeight + b + fontSize + b + fontFamily;

I have tried this using Safari, IE, Chrome, Firefox, with responsive design view, and it works. Trying to save, scale, and restore in my application created a foreground image with lower resolution on top of the old canvas. Trying to run through a range of media sizes the way it is shown above seems large I would think. I think I may be tempted to use the following accompanied with a good style sheet for the page layout.

我已经使用 Safari、IE、Chrome、Firefox 和响应式设计视图尝试过这个,并且它有效。尝试在我的应用程序中保存、缩放和恢复在旧画布上创建了一个分辨率较低的前景图像。我认为尝试按照上面显示的方式遍历一系列媒体尺寸似乎很大。我想我可能会想使用以下带有良好样式表的页面布局。

var px= 20-(((1366-canvas.width/3)/1366)*20);
context.font = +px+"px";
//place text here for this font
px= 12-(((1366-canvas.width/3)/1366)*12); 
context.font = +px+"px";
//place text here for this font

For other objects I would try to use the same approach but, limit images drawn to canvas with javascript, use as much css with % as you can and redraw images if necessary to prevent the user from scaling the page.

对于其他对象,我会尝试使用相同的方法,但是,限制使用 javascript 绘制到画布上的图像,尽可能多地使用带有 % 的 css,并在必要时重绘图像以防止用户缩放页面。

context.fillText  ("Click To Start", canvas.width/3, canvas.height/1.7);
context.strokeText  ("Click To Start", canvas.width/3, canvas.height/1.7);