web-dev-qa-db-fra.com

Obtention de la position du texte sélectionné

Actuellement, je reçois le texte sélectionné dans le navigateur en faisant ceci:

window.getSelection();

Maintenant, je dois afficher une info-bulle au-dessus de ce texte lorsque vous appuyez sur une touche personnalisée (notez que la souris ne peut plus être sur le texte), donc pour ce faire, j'ai besoin de la position absolue du texte sélectionné.

Existe-t-il un moyen de le faire, en enveloppant peut-être ce texte dans une balise et en obtenant ensuite les décalages? Il doit simplement fonctionner dans Chrome, pas tous les navigateurs.

38
Ecarrion

Le moyen le plus simple consiste à insérer un élément marqueur temporaire au début ou à la fin de la sélection et à obtenir sa position. J'ai déjà montré comment faire cela sur Stack Overflow: Comment puis-je positionner un élément à côté de la sélection de texte utilisateur?

15
Tim Down
s = window.getSelection();

Renvoie une sélection. Alors essayez

s = window.getSelection();
oRange = s.getRangeAt(0); //get the text range
oRect = oRange.getBoundingClientRect();

oRect sera le rectangle englobant en coordonnées (fixes) du client.

57
Jerinaw

Avant d'utiliser getBoundingClientRect, vous devez savoir cette note :

Le brouillon de travail CSSOM spécifie qu'il renvoie un ClientRect pour chaque boîte de bordure

Et par ce "standard":

Pour un élément en ligne, les deux définitions sont identiques. Mais pour un élément de bloc, Mozilla ne renverra qu'un seul rectangle.

Donc, si quelqu'un qui lit ce post veut une solution générale pour des positions et des dispositions plus précises de textes sélectionnés, je suggère les approches suivantes:

Option 1: Trouvez le point de départ et d'arrivée exact des textes en en insérant des éléments invisibles . Ensuite, calculez les rectangles de ligne sélectionnés avec la hauteur de ligne calculée et la largeur du conteneur extraites. API utilisées: window.getComputedStyle .

  • Pro: le résultat serait le plus précis pour chaque ligne de texte.
  • Con: 1) Si la sélection se fait sur plusieurs nœuds avec différentes hauteurs et largeurs de ligne, l'algorithme devient complexe. 2) Et vous devez implémenter l'algorithme de calcul, qui prend trop de temps lors de l'implémentation d'une fonctionnalité simple.

Option 2: Enveloppez chaque texte avec un élément en ligne soigneusement conçu, en extrayant la disposition de chaque boîte et fusionnez les résultats en lignes.

  • Pro: Fonctionne pour toutes les sélections continues (cela signifie essentiellement tous les cas dans les implémentations de navigateur courantes.). Assez bonne précision pour chaque ligne de textes.
  • Con: 1) Son résultat est un peu inexact dans certains cas, car il ajoute des largeurs d'erreur de crénage . 2) C'est très lent sur une très large sélection de textes.

Pour l'option 2, rangeblock est une implémentation existante avec une API simple qui vous donne la disposition en absolution de chaque ligne de texte:

let block = rangeblock.extractSelectedBlock(window, document);
console.info("Text layout: " + JSON.stringify(block.dimensions));
// output: Text layout: {Left: 100, Top: 90, Width: 200, Height: 50}
0
lowatt