Javascript range.setStart是否仅使用字符偏移量?
我对Javascript非常陌生,过去几天我一直在阅读文档,试图弄明白这一点。我终于不得不在这里炫耀我的无知了 我有一个整数,它是段落中字符的索引。我想找到这个角色的边界矩形。我一直试图通过创建一个包含字符的范围来实现这一点 所以我试过:Javascript range.setStart是否仅使用字符偏移量?,javascript,html,ios,Javascript,Html,Ios,我对Javascript非常陌生,过去几天我一直在阅读文档,试图弄明白这一点。我终于不得不在这里炫耀我的无知了 我有一个整数,它是段落中字符的索引。我想找到这个角色的边界矩形。我一直试图通过创建一个包含字符的范围来实现这一点 所以我试过: var range = document.createRange(); range.setStart (node, offsetInsideNode); 对于节点,我尝试传入段落元素,对于OffsetSideNode,我传入characterOffset整数
var range = document.createRange();
range.setStart (node, offsetInsideNode);
对于节点,我尝试传入段落元素,对于OffsetSideNode,我传入characterOffset整数
但是后来我发现:“如果node元素可以有子节点,那么offsetInsideNode参数指定node元素的childNodes集合中的子节点的位置,否则它指定node元素文本内容中的字符位置。”
但我只想使用角色的位置。我不知道怎么做,因为它似乎只想使用子节点位置。我猜我错过了什么
假设我有一段话:
<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个字符的边界矩形,我该怎么做呢?我是不是找错了方向,有一个更简单的方法我忽略了
谢谢
注:
- 仅限javascript
- 没有图书馆
- 没有jquery
- 对于iOS设备上的UIWebview
- 我希望这就是您要找的。此函数基本上获取要在中查找第n个元素的内容,将其拆分为字符,在不计算HTML标记的情况下查找第n个
nth
,将第n个nth
包装在临时范围内,并读取offsetTop
和offsetLeft
,然后将其替换为原始内容。然后将偏移量x和y作为对象返回
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;
}
我做了一把小提琴,你可以试一下
使用该函数定位红色矩形并将其缩放到第n个字符。据我所知,您需要 只有字符位置 以指定选择的范围,而不是某些节点偏移。我相信我也有同样的问题。偏移量可以通过寻址节点或字符来创建。
Range.setStart
方法一次可以做两件事,这是一件痛苦的事情,但是文档给出了您必须做的事情:
如果startNode是Text、Comment或CDATA节类型的节点,则startOffset是startNode开头的字符数
见:
因此,可以通过寻址元素的文本节点来指定字符索引范围。下面是我提出的一个(乐观的)解决方案
假设您有一个文档,并且希望向选定的文本片段添加粘性CSS样式的黄色高亮。在Javascript中,创建一个范围并选择元素。添加范围,但首先选择文本节点。偏移量将引用字符,而不是节点
// 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(元素)
提取textNode。注意,这个函数非常乐观。它假定节点列表包含一个textNode作为第一个元素,而不必是这样。如何获得该节点取决于您,这里只显示了一种简单的方法。我假设迭代列表并检查节点的文本或CDATA类型就足够了
将创建范围并设置起点和终点。当“node”对象是textNode时,偏移量对字符进行寻址。看看这把小提琴,看看它在演奏
例如,所示代码获取所选范围,并用样式化的span元素将其包围,以突出显示从字符50
到200
的范围
我不确定你到底想得到什么。特定角色相对于窗口的x和y坐标?哇,我真的很感谢你的努力!我确实做了一个小改动,以修复当字符是html标记前的最后一个字符时的错误,我添加了:“if(nth==count&&&!tag&&arr[I]!='>')”。这样看来,一切都正常(尽管我还没有彻底检查)。再次感谢:)很高兴你觉得它有用。当你彻底测试了它之后,如果你发现有些东西不起作用,请随意更新你认为合适的答案。酷。我还注意到它也必须是“nthCharacterNumber==count-1”,才能使整个过程以零为基础。(因为for循环在实际使用它之前增加计数)。我无法对if语句进行重新排序以纠正这一问题,因为我现在在第一条评论中提到的最后一条if语句中使用了“tag”。我也可以通过将count初始化为-1来解决这个问题,但我认为这种方式更为明显。
// 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.