【问题标题】:HTML5 Canvas Font Size Based on Canvas SizeHTML5 Canvas 字体大小基于 Canvas 大小
【发布时间】:2014-04-08 16:40:38
【问题描述】:

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

画布上的大部分元素也是根据画布的宽度和高度设置的,因此它们的尺寸会缩小并根据画布的大小进行定位。

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

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

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    只需用一个因子缩放font-size

    基础

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

    这将创建以下关系:

    ratio = 80 / 1000 = 0.08
    

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

    fontSize = 1000 * ratio = 80;
    

    我们看到我们有 80 个字体如预期的那样。

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

    fontSize = 500 * ratio = 40;
    

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

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

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

    解决方案

    由此产生的最终代码本质上非常简单:

    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
    }
    

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

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

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

    Live demo

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

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      [还有更高效的...]

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

      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
          },
      }
      

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

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

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

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

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

      【讨论】:

      • 哇,我每次使用 fillText 来处理游戏的各种元素时都必须添加很多代码。不过,我可以看到它是如何工作的。
      • 我已经添加到我的答案中,以显示定义字体大小的“代码一次并且仍然可扩展”的方式。祝你的项目好运!
      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

        我不喜欢为任何应用程序使用确定的宽度或高度。相反,我使用 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;
        

        我已经使用 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
        

        对于其他对象,我会尝试使用相同的方法,但是,限制使用 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);  
        

        【讨论】:

          【解决方案5】:

          另一种按比例绘制文本(或其他任何内容)的技术是使用画布转换矩阵。

          诀窍是在绘制之前将坐标系 (0, 0) 临时移动到文本插入点并围绕该点进行缩放。

          1. 保存绘图上下文
          2. 使用 context.translate() 将坐标系移动到文本插入点
          3. 使用 context.scale() 以所需的比例因子放大/缩小
          4. 在翻译点 (0, 0) 处插入文本。
          5. 恢复上下文。

          x, y 点以所需 scale 绘制 text 的示例代码:

          function drawText(context, x, y, text, scale){
              context.save();
              context.translate(x, y)
              context.scale(scale, scale);
              context.fillText(text, 0, 0);
              context.restore();
          }
          

          要绘制文本居中使用

          context.textAlign ="center";
          context.textBaseline = "middle";
          

          【讨论】:

            猜你喜欢
            • 2011-08-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-14
            • 1970-01-01
            • 2012-12-05
            • 1970-01-01
            相关资源
            最近更新 更多