Вычислить точный символ \ высоту строки в JavaScript

Я работаю с холстами и не могу придумать какое-либо решение или найти ответ на мою проблему.

У меня есть шрифт, который содержит символы \ символы разных размеров - высоты и ширины.

Я хочу нарисовать некоторые символы (символы) из шрифта, а некоторые сверху \ вниз символа. Проблема в том, что я не могу найти способ получить точную высоту в пикселях символа, который я рисую, и это вызывает нежелательные пробелы между центральным символом и символом сверху \ вниз (для получения ширины В строке есть функция context.measureText(theText)).

например допустим, я хочу, чтобы символом "Х" был мой центральный символ. и '-' чтобы быть на вершине. Это выглядит так

-
Икс

но теперь между 'X' и '-' есть место, которое я не хочу.

Кто-нибудь может мне с этим помочь?

Спасибо

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

Просто чтобы опираться на предыдущие хорошие ответы здесь. Это даст высоту и ширину (у меня были некоторые проблемы с некоторыми символами юникода и 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);
}

Хорошо, хорошо попробовал этот код, и мне пришлось немного изменить его, чтобы он работал.

это код после того, как мы нашли последнюю строку с непрозрачным пикселем.

так что, если кому-то это нужно просто замените Наслаждайтесь.

    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++;
   }
Другие вопросы по тегам