开发者

How to get position of every character

开发者 https://www.devze.com 2023-01-28 02:23 出处:网络
How to get position (left, top) of every characters in some node? I know just one method: wrap every character in it\'s own tag and then we can get it\'s coo开发者_Go百科rdinate. But it\'s bit slowlyI

How to get position (left, top) of every characters in some node? I know just one method: wrap every character in it's own tag and then we can get it's coo开发者_Go百科rdinate. But it's bit slowly


I've found answer on my question — Range interface can present all information that I need (More info — http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html).


You could cache the widths of characters that you already have seen.

function findOffset(index) {
  // Set some variables early on
  var sizes          = {},
      text           = "The text you are getting an offset from.",
      lineHeight     = 16,  // You can get this dynamically if you want
      containerWidth = 500, // Same with this one
      leftOffset     = 0,
      topOffset      = 0,
      i              = 0,
      cur;

  // Loop through and count up the sizes of each character until this one
  for (; (i < text.length) && (i <= index); i++) {

    // Set the current character
    cur = text.charAt(i);

    // Check to see if we have a size
    if ( typeof size[cur] == "undefined" ) {
      // If not: Wrap it in a span (You seemed to already know how to do this)
      // then cache the result
      size[cur] = findWidthByTemporarilyWrappingInASpan(text, i);
    }

    // If it's greater than a line can hold, we'll wrap
    if ( (sizes[cur] + leftOffset) > containerWidth ) {

      // Reset the left offset
      leftOffset = 0;

      // Increment the top offset
      topOffset += lineHeight;
    }
    // Otherwise, increment from the left
    else {
      leftOffset += sizes[cur];
    }
  }

  // return an object with the coordinates
  return {
    leftOffset: leftOffset,
    topOffset : topOffset
  };
}

Then you can even memoize each index that you go grab and start from a close by one the next time you call this function. This means you stay off the dom except for usually not too much more than ~50 (alphanumeric + punctuation, etc) times, rather than for each character.

This would certainly work for monospaced fonts, but I think there is some merit to it for other types. You'd just have to do the wrapping research for different browsers.

Also, note that this assumes left-justification, etc. It's more of an idea than an actual code solution.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号