【问题标题】:Calculate exact character\string height in javascript在javascript中计算精确的字符\字符串高度
【发布时间】:2013-05-24 20:12:50
【问题描述】:

我正在使用画布,我想不出任何解决方案,或者在线找到我的问题的答案。

我的字体包含不同大小的符号\字符 - 高度和宽度。

我想从字体中绘制一些字符(符号),并在符号的顶部\底部绘制一些字符。 问题是我无法找到一种方法来获得我正在绘制的字符的确切高度(以像素为单位),并且它会导致中心符号与 top\down 之间的不需要的空格(用于获取一个字符串有函数 context.measureText(theText) )。

例如。假设我希望“X”成为我的中心符号。和 '-' 位于顶部。 是这样的

-
x

但现在“X”和“-”之间有我不想要的空格。

谁能帮我解决这个问题?

谢谢

【问题讨论】:

    标签: javascript canvas height character measure


    【解决方案1】:

    只是建立在以前的好答案的基础上。这将给出高度和宽度(我对某些 unicode 字符和 measureText 有一些问题,这是某些字符的唯一解决方案)。

    function measureTextHeight(fontSizeFace, text) {
      var width = 1500;
      var height = 500;
    
      var canvas = document.createElement("canvas");
      canvas.width = width;
      canvas.height = height;
      var ctx=canvas.getContext("2d");
      ctx.save();
      ctx.font=fontSizeFace;
      ctx.clearRect(0,0,width,height);
      ctx.fillText(text, parseInt(width * 0.1, 10), parseInt(height / 2, 10));
      ctx.restore();
      document.body.appendChild(canvas);
      var data = ctx.getImageData(0,0,width,height).data;
    
    
      var topMost = false;
      var bottomMost = false;
      var leftMost = false;
      var rightMost = false;
      for(var x=0; x<width; x++) {
        for(var y=0; (y<height) && (!leftMost); y++) {
          //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
          if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
            leftMost = x;
          }
        }
      }
      for(var y=0; y<height; y++) {
        for(var x=0; (x<width) && (!topMost); x++) {
          //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
          if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
            topMost = y;
          }
        }
      }
      for(var x=width-1; x>=0; x--) {
        for(var y=height-1; (y>=0) && (!rightMost); y--) {
          //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
          if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
            rightMost = x;
          }
        }
      }
      for(var y=height-1; y>=0; y--) {
        for(var x=width-1; (x>=0) && (!bottomMost); x--) {
          //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
          if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
            bottomMost = y;
          }
        }
      }
      return ({
         width: (rightMost - leftMost) + 1
        ,height: (bottomMost - topMost) + 1
      });
    }
    function getAlphaIndexForCoordinates(x,y,width,height) {
      return (((width*4*y)+4*x)+3);
    }
    

    【讨论】:

      【解决方案2】:

      好的,这段代码试过了,我不得不稍微修改一下才能让它工作。

      这是我们找到最后一行不透明像素后的代码。

      所以万一有人需要它。只需替换享受。

          var blnFound = false;
          var intCurrRow = 0;
      
          // Find the first line with a non-transparent pixel
          while(!blnFound && intCurrRow < last) 
          {
            for(intCurrCol = 0; intCurrCol < width; intCurrCol++) 
            {
              var intCurrDataIdx = intCurrRow * width * 4 + intCurrCol * 4 + 3;
              if(data[intCurrDataIdx]) 
              {
                first = intCurrRow;
                blnFound = true;
                break;
              }
           }
      
           // If we've got it then return the height
           if (blnFound)
           {
             return last - first;
           }
      
           intCurrRow++;
         }
      

      【讨论】:

        【解决方案3】:

        宽度很简单:画布的上下文有一个用于测量文本宽度的内置指标。

        // this will measure text width
        context.font = '14pt Verdana';
        var m=context.measureText(yourText);
        var theWidth=m.width;
        

        高度比较困难,因为 measureText 不计算高度。

        您通常可以使用字体大小来近似高度——这就是我所做的。

        但如果您真的需要更高的准确性,这里有一个函数可以检查文本的像素以计算其高度:

        function measureTextHeight(fontSizeFace) {
        
            // create a temp canvas
            var width=1000;
            var height=60;
            var canvas=document.createElement("canvas");
            canvas.width=width;
            canvas.height=height;
            var ctx=canvas.getContext("2d");
        
            // Draw the entire a-z/A-Z alphabet in the canvas
            var text="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            ctx.save();
            ctx.font=fontSizeFace;
            ctx.clearRect(0,0,width,height);
            ctx.fillText(text, 0, 40);
            ctx.restore();
        
            // Get the pixel data from the canvas
            var data = ctx.getImageData(0,0,width,height).data,
                first = false, 
                last = false,
                r = height,
                c = 0;
        
            // Find the last line with a non-transparent pixel
            while(!last && r) {
                r--;
                for(c = 0; c < width; c++) {
                    if(data[r * width * 4 + c * 4 + 3]) {
                        last = r;
                        break;
                    }
                }
            }
        
            // Find the first line with a non-transparent pixel
            while(r) {
                r--;
                for(c = 0; c < width; c++) {
                    if(data[r * width * 4 + c * 4 + 3]) {
                        first = r;
                        break;
                    }
                }
        
                // If we've got it then return the height
                if(first != r) return last - first;
            }
        
            // error condition if we get here
            return 0;
        }
        

        【讨论】:

        • 首先,非常感谢您的回复。我也想过这个解决方案,但是这个解决方案效率较低,与我的“高效”网站不匹配:) 没有更好的方法吗?
        • 这段代码如果你有效地使用它是非常高效的!请记住,您只需针对各种字体运行此代码一次。那么你永远拥有你的高度!如果您以像素为单位设置字体大小,您甚至可以在发布您的网站之前执行此操作,并将高度存储在 JSON 中以供您的网站使用。简单+高效!顺便说一句,这段代码每秒运行数百次,所以你真的可以动态地执行它。 ;)
        • 当然我会这样做以节省时间。但我正在绘制代表符号的字符,每个字符的大小不同。等等..但我想没有其他办法。谢谢分配。
        • 这太好了。感谢分享。
        • Altered the code 略微因为我看到这是未优化的...@markE 的建议也非常好,如果您有更改字体,您还可以动态生成高度并存储它们!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多