Estoy usando la distancia del lapso desde la parte superior para colocar el símbolo de intercalación verticalmente, eso funciona bien, y estoy usando el índice de la cadena multiplicado por el ancho de la letra para colocar el símbolo de intercalación horizontalmente, pero eso a veces funciona, a veces no. t.
Mire, por ejemplo, la segunda fila y haga clic en el primer "esto", no funciona correctamente, pero si hace clic dentro del último "esto", el símbolo de intercalación se coloca correctamente.
No puedo entender por qué, ¿no significa que una fuente de espacio único tiene exactamente lo mismo para cada letra que observé aquí para ser 10.1? Algo no funciona aquí y no puedo entender qué. jsviolín
let writeDiv = document.querySelector('#write'); let caret = document.querySelector('#caret') writeDiv.addEventListener('click', (e) => { if(e.target.tagName == 'SPAN'){ moveCaretOnClick(e) } }) function moveCaretOnClick(e) { let y = window.getSelection().focusOffset * 10.1 caret.style = `left: ${y}px; top: ${e.target.offsetTop + 3}px`; } @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap'); body, html{ margin: 0; height: 100%; width: 100%; } #write { font-family: 'Roboto Mono'; height: 100%; width: 100%; background: #1f2227; padding: 10px; color: white; box-sizing: border-box; } #caret{ height: 15px; width: 3px; background: #80ff00; display: inline-block; position: absolute; } .RowSpan{ width: 100%; display: inline-block; box-sizing: border-box; height: 20px; } <div id='write'> <span class='RowSpan'>This is some text</span> <span class='RowSpan'>this is some text this</span> </div> <div id='caret'></div>Editar: supongo que necesito la dimensión exacta de las letras; de lo contrario, a medida que avanza en la línea, la distancia aumenta más y más, debido a la multiplicación de cada letra. Si agrega más texto, la distancia se aleja cada vez más del clic.
Entonces, de alguna manera obtenga la dimensión exacta de las letras que siempre es consistente o encuentre otra forma.
Un poco incómodo, pero encontré la solución, resulta que solo tenía que agregar un 1 al focusOffset antes de multiplicar con cada letra, de lo contrario, básicamente se saltaría una letra. Creo que porque focusOffset comienza con un 0
let writeDiv = document.querySelector('#write'); let caret = document.querySelector('#caret') writeDiv.addEventListener('click', (e) => { if(e.target.tagName == 'SPAN'){ moveCaretOnClick(e) } }) function moveCaretOnClick(e) { let y = (window.getSelection().focusOffset + 1) * 9.6 caret.style = `left: ${y}px; top: ${e.target.offsetTop + 3}px`; } @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap'); body{ margin: 0; } #write { font-family: 'Roboto Mono'; height: 300px; width: 1200px; background: #1f2227; padding: 10px; color: white; } #caret{ height: 15px; width: 2px; background: #80ff00; display: inline-block; position: absolute; } .RowSpan{ width: 100%; display: inline-block; box-sizing: border-box; height: 20px; } <div id='write'> <span class='RowSpan'>This is some text</span> <span class='RowSpan'>this is some text this more more text BIGGERT TEXT and some small text and some stuff -- __ !%^ () {} and some more text even </span> </div> <div id='caret'></div>