我对Javascript很陌生,过去几天我一直在阅读文档,试图解决这个问题。我终于不得不求助于在这里炫耀我的无知。
我有一个整数,它是段落中字符的索引。我想找到这个角色的边界矩形。我一直试图通过制作一个包含该角色的范围来做到这一点。
所以我尝试过:
var range = document.createRange();
range.setStart (node, offsetInsideNode);
并且对于节点我尝试传入段落元素,而对于offsetInsideNode我传入了characterOffset整数。
但后来我发现:“如果节点元素可以有子节点,则offsetInsideNode参数指定节点元素的childNodes集合中子节点的位置,否则它指定文本内容中的字符位置节点元素。“
但我想只使用角色位置。我无法弄清楚如何做到这一点,因为它似乎只想使用子节点位置。我猜我错过了什么。
说我有一个段落:
<p xmlns="http://www.w3.org/1999/xhtml" class="s12" style="color: rgb(0, 0, 0);"><span class="mySpanClass">The</span> quick brown <b>fox</b> jumps over the lazy dog</p>
我想找到第n个角色的边界矩形,我该怎么做呢?我是在吠叫错误的树吗?我忽略了一种更为简单的方法吗?
感谢。
注释:
答案 0 :(得分:2)
我希望这就是你要找的东西。此函数基本上获取您要在其中找到的元素的内容,将其拆分为字符,查找nth
而不计算HTML标记,将nth
包装在临时范围内并读取{{1}在用原始内容替换它之前和offsetTop
。然后将偏移量x和y作为对象返回。
offsetLeft
像这样使用:
function nthCharOffset(nth, element){
var orgContent = element.innerHTML; // Save the original content.
var arr = orgContent.split(''); // Split every character.
// Few vars to control the upcoming loop
var content = '';
var tag = false;
var count = 0;
// Loop through every character creating a new string and wrapping the nth in a temporary span
for (var i = 0; i < arr.length; i++) {
// if inside tag, don't count this in the nth count
if (arr[i] == '<') tag = true
if (!tag) count++;
if (arr[i] == '>') tag = false;
// If this charactar is nth, wrap it in a temporary span
if (nth == count) content += '<span id="offset-check">' + arr[i] + '</span>';
else content += arr[i];
}
// Set the content with the temporary span.
element.innerHTML = content;
// Get the offset of the temporary span.
var offsetCheck = document.getElementById('offset-check');
var offset = {x: offsetCheck.offsetLeft , y: offsetCheck.offsetTop }
// Remove the span.
element.innerHTML = orgContent;
// Return the result.
return offset;
}
我做了一个小提琴,所以你可以测试它here。
This fiddle使用该函数将红色矩形定位并缩放为nthCharOffset(10, document.getElementById('element'));
个字符。
答案 1 :(得分:1)
据我所知,你想要
仅限角色位置
以指定选择的范围,而不是某个节点偏移。我相信我遇到了同样的问题。可以通过寻址节点或字符来创建偏移量。 Range.setStart
方法同时执行两项操作,这很痛苦,但文档会提供您必须执行的操作:
如果startNode是Text,Comment或CDATASection类型的节点,则startOffset是startNode开头的字符数。
请参阅:https://developer.mozilla.org/en-US/docs/Web/API/Range/setStart
因此,您可以通过寻址元素的文本节点来指定字符索引范围。这是我提出的(乐观)解决方案。
假设您有一个文档,并且您希望将粘性CSS样式的黄色高光添加到一段选定的文本中。在Javascript中,创建一个范围并选择该元素。添加范围,但首先选择textnode。然后,偏移将引用字符,而不是节点。
// Magic happens here
function getTextNodeFrom(element) {
// replace with more sophisticated method
return element.childNodes[0];
}
// Create the range as you normally would
function createRange(node, start, end) {
var range = document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
return range;
}
// Give it a nice name
function createRangeByCharacterOffset(element, start, end) {
// Rather than passing the element directly to createRange,
// extract the node first.
var textNode = getTextNodeFrom(element)
var range = createRange(textNode, start, end);
return range;
}
// To illustrate, let's surround the range with a highlighting span
function highlight () {
var span = document.createElement('span');
span.setAttribute('class', 'highlight');
return span;
}
var p = document.getElementsByTagName('p')[0];
createRangeByCharacterOffset(p, 50, 200)
.surroundContents(highlight()); // This performs the actual highlight.
首先,选择给定的p
元素。然后,我们使用函数getTextNodeFrom(element)
提取textNode。请注意,此功能非常乐观。它假定节点列表包含textNode作为第一个元素,但不一定是这种情况。您如何获得此节点取决于您,此处仅显示一个简单的方法。我会假设迭代列表并检查节点的Text或CDATA类型就足够了。
创建范围并设置开始和结束。当'node'对象是textNode时,偏移量对字符进行寻址。看看这个小提琴,看看它在行动。
例如,显示的代码采用所选范围并用样式化的span元素围绕它,以突出显示从字符50
到200
的范围。