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 coordinate. But it's bit slowly
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 coordinate. But it's bit slowly
Share Improve this question asked Nov 30, 2010 at 8:11 anton_byrnaanton_byrna 2,5551 gold badge18 silver badges31 bronze badges 2- I fear you don't have much choice except the method you described. To know the position of every character you must know the exact size of each letter and that's pretty much impossible task as each font has different size for each character.. – Shadow Wizzard Commented Nov 30, 2010 at 9:00
- Possible duplicate: stackoverflow./questions/5143534/… – Anderson Green Commented Jun 3, 2013 at 23:12
2 Answers
Reset to default 8I've found answer on my question — Range interface can present all information that I need (More info — http://www.w3/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.