【问题标题】:How to determine width of text in OpenSCAD?如何确定 OpenSCAD 中文本的宽度?
【发布时间】:2016-09-19 01:18:34
【问题描述】:

在 OpenSCAD 中,我希望能够创建一个接受 stringmodule,然后创建一个 3-D 对象,该字符串作为 text 嵌入在表面中。我希望对象比text 稍大,所以我需要知道text 的宽度以便创建大小合适的对象。

我不确定如何查询text 的宽度(高度由输入变量设置),或者是否可能。

如果不可能,是否有一个函数可以接受字符串和字体并预测渲染文本的宽度?

【问题讨论】:

    标签: text size openscad rulers


    【解决方案1】:

    目前无法查询生成的文本几何图形的实际大小。但是,根据要创建的模型,计算粗略估计并使用scale() 将文本调整到已知大小可能就足够了。

    // Fit text into a randomly generated area
    
    r = rands(10, 20, 2);
    length = 3 * r[0];
    w = r[1];
    
    difference() {
        cube([length, w, 1]);
        color("white")
            translate([0, w / 2, 0.6])
                linear_extrude(1, convexity = 4)
                    resize([length, 0], auto = true)
                        text("This is a Test", valign = "center");
    }
    

    【讨论】:

    • 使用这个答案作为指导,我创建了将文本标签的宽度和高度限制为立方体的已知宽度和高度的模型。 thingiverse.com/thing:2090732
    【解决方案2】:

    如果您使用与 OpenSCAD 捆绑在一起的 Liberation 字体或 Microsoft Core Fonts 包中的字体,您可以使用我的字体测量 OpenSCAD 库。例如:

    use <fontmetrics.scad>;
    length = measureText("This is a Test", font="Arial:style=Italic", size=20.);
    

    图书馆是here。我使用了一些 Python scripts 从 ttf 文件中提取指标(包括字距调整对),您可以使用脚本添加有关更多字体的信息。

    【讨论】:

      【解决方案3】:

      我找到了一种方法来确定 OpenSCAD 中文本字符的宽度。我做了一个 JavaScript 东西,可以让你输入字体名称和样式,它会输出 ascii 和扩展 ascii 字符(代码 0-255)的宽度比例数组。然后对于任何给定的字符,将此比例乘以字体大小以获得单个字符的宽度。从那里获取字符串的宽度或围绕圆柱体缠绕的字符的角宽度是微不足道的。

      生成OpenSCAD宽度数组的工具在这里:https://codepen.io/amatulic/pen/eYeBLva

      ...代码复制如下,您可以从这个回复中运行,或者粘贴到您自己的 HTML 文件中并在本地加载到您的浏览器中。

      只需输入字体属性,点击按钮,向下滚动即可查看使用说明。

      秘诀在于 JavaScript 的“画布”支持有一个“measureText()”方法,可以测量给定字体的任何文本的像素长度,如下所示:

      canvasContext.measureText(string).width
      

      所以这段代码的作用是在页面上使用一个虚拟画布来获取分配字体的上下文,任意 20 像素大小。然后它为从 0 到 255 的每个字符生成一个宽度数组,将每个字符除以 20 以获得与字体大小相比的无单位宽度比例。然后它会输出一行 OpenSCAD 代码,您可以将其粘贴到您的 OpenSCAD 脚本中。然后使用 OpenSCAD 的ord() 函数将任何字符转换为数字代码,然后用作宽度数组的索引。然后将此宽度乘以字体大小以得到字符宽度。

      <html>
      <!--
      by Alex Matulich, February 2022
      Thingiverse: https://www.thingiverse.com/amatulic/designs
      Website: https://www.nablu.com
      -->
      <head>
        <script type="text/javascript">
          var sctx;
      
          function initialize() {
            var canvas = document.getElementById("canvas");
            sctx = canvas.getContext("2d");
          }
      
          function charwidth(fontname, style) {
            sctx.font = (style + " 20px " + fontname).trim();
            var charlen = [];
            for (i = 0; i < 256; ++i) //{ charlen[i] = 10; console.log(i); }
              charlen[i] = sctx.measureText(String.fromCharCode(i)).width / 20;
            return charlen;
          }
      
          function generate() {
            var fontname = document.getElementById("fontname").value;
            var fontstyle = document.getElementById("fontstyle").value;
            var widths = charwidth(fontname, fontstyle);
            var arrayname = toCamelCase(fontname) + toCamelCase(fontstyle);
            var outputhtml = arrayname + " = [<br/>\n" + widths[0].toString();
            var len = widths.length;
            for (i = 0; i < len; ++i) outputhtml += ', ' + widths[i].toString();
            outputhtml += "<br/>\n];\n";
            document.getElementById("output").innerHTML = outputhtml;
            document.getElementById('usage').innerHTML = "<h3>Usage</h3>\n<p>The array above shows character width as a multiple of font size. To get the width of a character <code>&lt;char&gt;</code> given font size <code>&lt;fontsize&gt;</code> using the font \"" + fontname + " " + fontstyle + "\":</p>\n<p><code>&nbsp; charwidth = " + arrayname + "[ord(char)] * fontsize;<code></p>\n";
            document.getElementById('sample').innerHTML = "<h3>Font sample</h3>\n<p style=\"font: " + fontstyle + " 20px " + fontname + ";\">" + fontname + " " + fontstyle + ": 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</p>\n";
          }
          // convert the input array to camel case
          function toCamelCase(stringinput) {
            if (stringinput.length == 0) return '';
            var inputArray = stringinput.match(/[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g);
            result = "";
            for (let i = 0, len = inputArray.length; i < len; i++) {
              let currentStr = inputArray[i];
              let tempStr = currentStr.toLowerCase();
              // convert first letter to upper case (the word is in lowercase)
              tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1);
              result += tempStr;
            }
            return result;
          }
        </script>
      </head>
      
      <body onload="initialize()">
        <h1>OpenSCAD proportional font widths</h1>
        <form>
          <fieldset>
            <legend>Identify the font</legend>
            <input type="text" id="fontname" name="fontname" value="Liberation Sans">
            <label for="fontname">Font name</label><br />
            <input type="text" id="fontstyle" name="fontstyle" value="bold">
            <label for="fontstyle">Font style (bold, italic, etc. or leave blank)<br />
          </fieldset>
          <input type="button" onclick="generate()" value="Generate OpenSCAD font width proportions">
        </form>
        <h2>Copy and paste this code into OpenSCAD</h2>
        <div id="output" style="border:5px ridge silver; padding:1em; font-family:monospace;">
        </div>
        <div id="usage">
        </div>
        <div id="sample">
        </div>
        <canvas id="canvas"></canvas>
      </body>
      </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-29
        • 2012-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多