使用 Javascript 获取画布中的最大字体大小

2024-02-06

我正在绘制一个画布,需要在整个可用屏幕上(100% 宽度和高度)。我使用 JavaScript 设置画布的宽度和高度,如下所示

  var w = window.innerWidth;
  var h = window.innerHeight;
  var canvas = document.getElementById("myCanvas");
  canvas.width  = w;
  canvas.height = h;

设置画布后,我需要在其中绘制一些文本,这些文本需要获得最大可用字体大小。请帮助我找到如何以最大字体大小显示文本的方法。文本可以包含单个字符(大写和小写)或字符串,也可以包含数字。我需要用 javascript 而不是 jquery 来完成它。

感谢您的帮助。


挑战

作为画布'measureText目前不支持测量高度(上升+下降),我们需要做一些 DOM 技巧来获取行高。

由于字体或字体的实际高度不一定(很少)与字体相对应size,我们需要一种更准确的测量方法。

Solution

小提琴演示 https://jsfiddle.net/epistemex/m2j10rzs/

结果将是垂直对齐的文本,其宽度始终适合画布。

该解决方案将自动获取字体的最佳大小。

第一个功能是包装measureText以支撑高度。如果文本指标的新实现不可用,则使用 DOM:

function textMetrics(ctx, txt) {

    var tm = ctx.measureText(txt),
        w = tm.width,
        h, el;  // height, div element
    
    if (typeof tm.fontBoundingBoxAscent === "undefined") {
    
        // create a div element and get height from that
        el = document.createElement('div');
        el.style.cssText = "position:fixed;font:" + ctx.font +
                           ";padding:0;margin:0;left:-9999px;top:-9999px";
        el.innerHTML = txt;

        document.body.appendChild(el); 
        h = parseInt(getComputedStyle(el).getPropertyValue('height'), 10);
        document.body.removeChild(el);

    } 
    else {
        // in the future ...
        h = tm.fontBoundingBoxAscent + tm.fontBoundingBoxDescent;
    }

    return [w, h];
}

现在我们可以循环找到最佳大小(这里不是很优化,但可以达到目的 - 我刚刚写了这个,所以那里可能存在错误,其中一个是文本是否只是一个不超过宽度的字符身高之前)。

该函数至少需要两个参数,上下文和文本,其他参数是可选的,例如字体名称(仅名称)、容差 [0.0, 1.0](默认 0.02 或 2%)和样式(即粗体、斜体等):

function getOptimalSize(ctx, txt, fontName, tolerance, tolerance, style) {

    tolerance = (tolerance === undefined) ? 0.02 : tolerance;
    fontName = (fontName === undefined) ? 'sans-serif' : fontName;
    style = (style === undefined) ? '' : style + ' ';
    
    var w = ctx.canvas.width,
        h = ctx.canvas.height,
        current = h,
        i = 0,
        max = 100,
        tm,
        wl = w - w * tolerance * 0.5,
        wu = w + w * tolerance * 0.5,
        hl = h - h * tolerance * 0.5,
        hu = h + h * tolerance * 0.5;
    
    for(; i < max; i++) {

        ctx.font = style + current + 'px ' + fontName;
        tm = textMetrics(ctx, txt);
        
        if ((tm[0] >= wl && tm[0] <= wu)) {
            return tm;
        }
        
        if (tm[1] > current) {
            current *= (1 - tolerance);
        } else {
            current *= (1 + tolerance);
        }            
    }
    return [-1, -1];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Javascript 获取画布中的最大字体大小 的相关文章

  • Kendo UI 网格过滤器日期格式

    在我的剑道网格中 我想更改过滤器中的日期格式 例如 2015年1月30日至2015年1月30日 我已经更改了开始日期的日期格式 field StartDate title Start Date width 30 format 0 MMM d
  • 这段代码有什么问题。如果用户选择或不选择复选框,为什么它仍然显示 MsgBox? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 无论我是否选择复选框 它仍然会给出
  • 在 iPad 上调试 Javascript

    我想知道人们是否找到了任何有用的工具来在未越狱的 iPad 上调试 javascript 这是一款用于工作的 iPad 因此无法越狱 通过一些繁琐的步骤 我已经在 iPad 上运行了 firebug lite 但是我的 javascript
  • 共享工作线程在重新加载页面时终止

    为什么 Shared Worker 在重新加载页面时死掉了 应该是复活了我该如何解决这个问题 重新加载前 重新加载后 在 example com 上按 F5 家长工人 var port new SharedWorker app worker
  • JS 在两个或多个点之间画线

    我需要在两个标签或标签之间画一条线 Example http caitriona github io connect the dots http caitriona github io connect the dots 我需要做这样的事情
  • 将 Json 数据返回给 Ajax 调用

    我在 MVC 中有一个方法 我将其发布到它 并且我需要返回一些数据以进行处理 这是我发布到的 MVC 方法 返回值是 json 数据 HttpPost public JsonResult GetCalculateAmortizationSc
  • Javascript 无法正确排序 DECIMAL 数字

    我有一些代码可以按字母顺序对名称进行排序 我遇到的问题是它处理小数的方式 它对名称进行排序 如下所示 我宁愿它按数字递增 DOG 1 0510 DOG 1 1031 DOG 11 1792 DOG 12 0920 DOG 12 1170 D
  • 从 ES6 模块导入函数表达式或函数声明有什么区别?

    据我了解 参见第 16 3 2 1 节 http exploringjs com es6 ch modules html ES6 允许函数 类导出操作数使用不同的语法 区别在于导出的函数是否需要在导入时解释为函数声明 在这种情况下 您可以编
  • 光标:IE 8 和 9 中的自动行为

    我想要的是为整个正文标记指定cursor pointer 这样页面的背景是可点击的 但我也希望页面的其余部分像以前一样工作 所以我尝试为div设置cursor auto 其中包含这一页 在 FF Chrome 和 safari 中 它工作得
  • TypeError:cli.init 不是 React Native 的函数

    在 MacBook Air M1 芯片中运行 npx react native init appName 时 TypeError cli init is not a function at run opt homebrew lib node
  • 预加载 javascript 和 css 文件

    我目前正在开发一个移动网站 该网站大量使用图像 CSS 和 JavaScript 例如 它使用未压缩的 150KB 的库 我为图像构建了一个预加载器 效果相当好 function loadImages images var sum 0 fo
  • 如何检查侧边栏视图是否已经在主干中渲染?

    通常 用户通过主页进入网站 然后我在那里渲染侧边栏视图 接下来 用户单击链接 路由器呈现另一个视图并替换原始内容视图 侧边栏视图不会重新渲染 当用户在子页面上单击刷新时 侧边栏不会呈现 如何检查视图是否存在并且已渲染 划分责任并坚持下去 不
  • 将屏幕宽度获取到 javascript 变量中并通过 ajax 将其发送到 php 页面以避免页面加载

    这是JS检测我的页面命名上的屏幕分辨率index html并将其发送到 php 以便可以使用以下方式检索值 GET 这是我的PHP文件命名的内容process php
  • 在 Windows 上静默安装 Qt55 Enterprise

    编辑 在 Qt 支持的帮助下 我已经解决了如何自动化 Qt 企业安装程序的这两个部分 下面是脚本调用 我正在尝试在 Windows 8 1 和 Windows 10 上静默安装 Qt 5 5 1 Enterprise 使用 script 开
  • 带有桌子的嵌套表

    我在应用了表排序器的表中嵌套了表 它在嵌套表中添加了排序标题 但是它们没有对行进行排序 并且抛出了JavaScript错误 我想拥有 嵌套表不可排序 巢表上的排序实际上可以工作 但不是现状 您的第一个选择要容易得多 使嵌套表不可排序 像这样
  • 如何获取从 Express (Node.js) 中的表单传递的数据

    我想获取使用表单从页面传递的数据 并在重定向的页面中使用该数据 我的客户端有这个表格
  • 为什么我从 c# 到 js 得到不同的 MD5 哈希值?

    我有一个用于加密密码的 C 函数 System Security Cryptography MD5CryptoServiceProvider md5Provider new System Security Cryptography MD5C
  • 检测 html 选择框上的编程更改

    有没有办法让 HTML 选择元素在每次以编程方式更改其选择时调用函数 当使用 JavaScript 修改选择框中的当前选择时 IE 和 FF 都不会触发 onchange 此外 更改选择的 js 函数是框架的一部分 因此我无法更改它以在结束
  • 如何使用 Chart.js 版本 3.2.1 在圆环图中添加文本

    我正在使用 Canvas 在 HTML 中使用 如何使用在圆环图中添加文本 这是我的 javascript 代码和 HTML 代码 我使用了图表js版本3 2 1 所以请给出相同版本 3 的解决方案 var overallStatsCanv
  • 为什么 phantomjs 不能在 MacOS Sierra 中工作?

    我们正在使用phantomjs 1 9 1 macosx phantomjs 2 0 0 macosx哪一个工作得很好OS X 埃尔卡皮坦更新后macOS 塞拉利昂它会引发以下错误 phantomjs 1 9 1 macosx phanto

随机推荐