我正在为 iOS 开发一个富文本编辑器,并且大部分都可以工作,但是遇到了无穷无尽的问题,以确保当用户开始输入时光标在视口中可见。
我想出了一个新颖的方法:在光标位置插入一个跨度,滚动到该跨度,然后将其删除。(如果跨度在屏幕上,我还没有只滚动。)这是我写的:
document.addEventListener('keypress', function(e) {
jumpToID();
}, false);
function jumpToID() {
var id = "jumphere2374657";
var text = "<span id='" + id + "'> </span>"
document.execCommand('insertHTML', false, text);
var element = document.getElementById(id);
element.scrollIntoView();
element.parentNode.removeChild(element);
}
在某些情况下,这工作得很好,在某些情况下,它会在每次按键之间留下一个不间断的空间,只删除 <span></span> 标记。有任何想法吗?如果有人有建议,我愿意接受更好的方法。我对让光标出现有多难感到有点震惊,但是 JS 对我来说是新的。
编辑
这是有效的代码:
var viewportHeight = 0;
function setViewportHeight(vph) {
viewportHeight = vph;
if(viewportHeight == 0 && vph != 0)
viewportHeight = window.innerHeight;
}
function getViewportHeight() {
if(viewportHeight == 0)
return window.innerHeight;
return viewportHeight;
}
function makeCursorVisible() {
var sel = document.getSelection(); // change the selection
var ran = sel.getRangeAt(0); // into a range
var rec = ran.getClientRects()[0]; // that we can get coordinates from
if (rec == null) {
// Can't get coords at start of blank line, so we
// insert a char at the cursor, get the coords of that,
// then delete it again. Happens too fast to see.
ran.insertNode( document.createTextNode(".") );
rec = ran.getClientRects()[0]; // try again now that there's text
ran.deleteContents();
}
var top = rec.top; // Y coord of selection top edge
var bottom = rec.bottom; // Y coord of selection bottom edge
var vph = getViewportHeight();
if (top < 0) // if selection top edge is above viewport top,
window.scrollBy(0, top); // scroll up by enough to make the selection top visible
if (bottom >= vph) // if selection bottom edge is below viewport bottom,
window.scrollBy(0, bottom-vph + 1); // scroll down by enough to make the selection bottom visible
}
viewportHeight 比 Web 应用程序需要的复杂。对于移动应用程序,我们需要考虑键盘,因此提供一种手动设置 viewportHeight 以及从 window.innerHeight 自动设置的方法。