Boucle avec wordwrap
YameFAZE
Messages postés
201
Date d'inscription
Statut
Membre
Dernière intervention
-
yg_be Messages postés 23541 Date d'inscription Statut Contributeur Dernière intervention -
yg_be Messages postés 23541 Date d'inscription Statut Contributeur Dernière intervention -
Bonjour à tour,
J'ai à la base wordwrap qui me coupe une chaîne tous les X caractères. Je cherche à faire une boucle qui à chaque coupure incrémenterait automatiquement le nombre de caractères pour faire une nouvelle coupure avec un peu plus de caractères... et je n'y arrive pas. Le but final est en fait d'avoir un texte qui suit le côté droit oblique (diagonale) d'une image en float left. Et comme en CSS pour le moment ce n'est pas faisable je suis obligé de passer par un bidouillage PHP.
On pourrait imaginer une boucle qui ferait quelque chose comme :
Sauf que ça ne fonctionne pas. Et c'est logique puisque au lieu de juste couper le texte une seule fois elle coupe le texte à chaque nouvelle incrémentation. Et si je mets le echo en-dehors de la boucle là j'ai bien le texte une seule fois mais avec le même nombre de caractères à chaque coupure.
Donc est-ce que je m'y prends mal ou alors y a-t-il une autre solution ?
Merci d'avance.
J'ai à la base wordwrap qui me coupe une chaîne tous les X caractères. Je cherche à faire une boucle qui à chaque coupure incrémenterait automatiquement le nombre de caractères pour faire une nouvelle coupure avec un peu plus de caractères... et je n'y arrive pas. Le but final est en fait d'avoir un texte qui suit le côté droit oblique (diagonale) d'une image en float left. Et comme en CSS pour le moment ce n'est pas faisable je suis obligé de passer par un bidouillage PHP.
On pourrait imaginer une boucle qui ferait quelque chose comme :
<?php $texte = 'bla bla bla...'; $nbr_caracteres = 10; $nbr_lignes = 1; do { echo wordwrap($texte, $nbr_caracteres, '<br />'); $nbr_caracteres = $nbr_caracteres + 5; $nbr_lignes++; } while ($nbr_lignes < 10); ?>
Sauf que ça ne fonctionne pas. Et c'est logique puisque au lieu de juste couper le texte une seule fois elle coupe le texte à chaque nouvelle incrémentation. Et si je mets le echo en-dehors de la boucle là j'ai bien le texte une seule fois mais avec le même nombre de caractères à chaque coupure.
Donc est-ce que je m'y prends mal ou alors y a-t-il une autre solution ?
Merci d'avance.
A voir également:
- Boucle avec wordwrap
- Boucle excel sans macro - Forum Excel
- Mon pc s'allume et s'éteint en boucle ✓ - Forum Matériel & Système
- Mise à disposition de boucle locale dédiée ✓ - Forum Freebox
- Vlc lire en boucle ✓ - Forum Lecteurs et supports vidéo
- Xiaomi s'éteint tout seul et se rallume en boucle - Forum Xiaomi
3 réponses
yg_be
Messages postés
23541
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 584
bonjour, tu décris la technique que tu utilises, et qui ne fonctionne pas.
pourrais-tu décrire ce que tu essaies d'obtenir, via un exemple?
pourrais-tu décrire ce que tu essaies d'obtenir, via un exemple?
J'ai écris un bout de code qui fonctionne mais c'est vraiment du bidouillage... et je ne trouve pas ça très propre. En effet, étant donné que mon image est en float: left, le texte se colle naturellement contre l'image, mais le paragraphe lui dans le flux passe sous l'image, du coup je ne peux pas jouer sur le margin-left proprement, je suis obligé de bidouiller avec du position: relative et du margin-left négatif.
Y a-t-il un moyen pour que avec le positionnement float de l'image le paragraphe ne passe pas sous l'image ? Ou alors il va falloir que j'utilise une Flexbox.
Et autre question, mon bout de code fonctionne plutôt bien si l'on n'est pas choqué par le fait que les mots soient complètement coupés... comment faire pour que les mots ne soient pas coupés ou alors qu'ils soient coupés proprement avec un "-" ?
Ci-dessous mon code (je pense qu'il y a moyen de l'améliorer bien-sûr) :
Et voici ce que ça donne dans le navigateur (j'ai mis un background orange pour voir comment se comporte les paragraphes) :

Y a-t-il un moyen pour que avec le positionnement float de l'image le paragraphe ne passe pas sous l'image ? Ou alors il va falloir que j'utilise une Flexbox.
Et autre question, mon bout de code fonctionne plutôt bien si l'on n'est pas choqué par le fait que les mots soient complètement coupés... comment faire pour que les mots ne soient pas coupés ou alors qu'ils soient coupés proprement avec un "-" ?
Ci-dessous mon code (je pense qu'il y a moyen de l'améliorer bien-sûr) :
/* On récupère le texte à couper et on l'intègre dans la chaîne $str... */ $str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence.'; /* ...et on détermine le nombre de caractères de la première ligne. */ $nbr_max_caract_ligne_1 = 35; /* Si le nombre total de caractères de la chaîne dépasse $nbr_max_caract_ligne1,... */ if (strlen($str) > $nbr_max_caract_ligne_1) { /* ...on initialise le tableau $ligne,... */ $ligne = array(); /* ...on définit la valeur de la première entrée de $ligne,... */ $i_ligne = 1; /* ...on définit le départ de la première coupure,... */ $start = 0; /* ...on définit le nombre de caractères de la première coupure,... */ $nbr_max_caract_ligne = 35; /* ...on définit un nombre maximum de coupures,... */ $nbr_max_lignes = 10; /* ...on définit une valeur de départ pour la position des paragraphes,... */ $position = 0; /* ...on définit une valeur de départ pour la largeur des paragraphes,... */ $largeur = 98; /* ...puis on lance une boucle. */ do { /* On coupe la chaîne à partir de $start jusqu'à $nbr_max_caract_ligne et on intègre la partie récupérée comme première entrée dans $ligne,... */ $ligne[$i_ligne] = substr($str, $start, $nbr_max_caract_ligne); /* ...on affiche l'entrée,... */ echo '<p style="left: '.$position.'%; width: '.$largeur.'%;">'.$ligne[$i_ligne].'</p>'; /* ...on incrémente $i_ligne de 1,... */ $i_ligne++; /* ...on incrémente $start,... */ $start = $start + $nbr_max_caract_ligne; /* ...on incrémente $nbr_max_caract_ligne,... */ $nbr_max_caract_ligne = $nbr_max_caract_ligne + 1; /* ...on décrémente $position,... */ $position = $position - 0.3; /* ...puis on incrémente $largeur avant de relancer la boucle. */ $largeur = $largeur + 0.3; /* La boucle doit tourner tant que $i_ligne est inférieur à $nbr_max_lignes. */ } while ($i_ligne <= $nbr_max_lignes); /* Sinon..., */ } else {}
Et voici ce que ça donne dans le navigateur (j'ai mis un background orange pour voir comment se comporte les paragraphes) :

Bon voilà, ça prend forme petit à petit. Au final j'utilise des span pour chaque ligne le tout englobé dans un seul paragraphe. C'est plus propre. J'ai réussi à faire en sorte que les mots ne soient pas coupés. Les premières lettres du mot coupé sont supprimées de la ligne et ajoutées au début de la ligne suivante. Il faut encore que j'améliore le code car pour le moment la longueur des lignes ne prend pas en compte ces suppressions et ajouts, du coup je me retrouve avec un problème de longueur de caractères sur certaines lignes.

/* On récupère le texte à couper et on l'intègre dans la chaîne $str. */ $str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence.'; /* On détermine le nombre maximum de caractères de la première ligne d'affichage. */ $nbr_max_caract_ligne_1 = 35; /* On débute l'affichage du texte. */ echo '<p>'; /* Si le nombre total de caractères de la chaîne dépasse $nbr_max_caract_ligne1 on suit les instructions spécifiques. */ if (strlen($str) > $nbr_max_caract_ligne_1) { /* On initialise le tableau $sub_str. */ $sub_str = array(); /* On définit la valeur de la première entrée de $sub_str. */ $i_sub_str = 1; /* On définit le départ de la première coupure. */ $start = 0; /* On définit le nombre de caractères de la première coupure. */ $nbr_max_caract_ligne = 35; /* On définit un nombre maximum de coupures. */ $nbr_max_lignes = 10; /* On définit une valeur de départ pour la marge gauche des span. */ $marge_gauche = 0; /* On initialise une boucle. */ do { /* On coupe la chaîne à partir de $start jusqu'à $nbr_max_caract_ligne et on enregistre la sous-chaîne dans $sub_str. */ $sub_str[$i_sub_str] = substr($str, $start, $nbr_max_caract_ligne); /* On recherche la position du dernier espace dans $sub_str[$i_sub_str] et on l'enregistre dans $pos_esp. */ $pos_esp = strrpos($sub_str[$i_sub_str], ' '); /* On récupère le début de la sous-chaîne jusqu'à la position du dernier espace et on l'enregistre dans $start_sub_str. */ $start_sub_str = substr($sub_str[$i_sub_str], 0, $pos_esp); /* On débute l'affichage de la sous-chaîne. */ echo '<span style="margin-left: '.$marge_gauche.'%;">'; /* S'il ne s'agit pas du premier passage de la boucle on suit les instructions spécifiques. */ if ($i_sub_str > 1) { /* On affiche la fin de la sous-chaîne précédente au début de la sous-chaîne suivante. */ echo '<span style="color: red;">'.$end_sub_str.'</span>'; } /* On termine l'affichage de la sous-chaîne. */ echo $start_sub_str.'</span><br />'; /* On récupère la fin de la sous-chaîne à partir de la position du dernier espace et on l'enregistre dans $end_sub_str. */ $end_sub_str = substr($sub_str[$i_sub_str], $pos_esp); /* On incrémente $i_sub_str de 1. */ $i_sub_str++; /* On incrémente $start. */ $start = $start + $nbr_max_caract_ligne; /* On incrémente $nbr_max_caract_ligne. */ $nbr_max_caract_ligne = $nbr_max_caract_ligne + 1; /* On décrémente $marge_gauche. */ $marge_gauche = $marge_gauche - 0.3; /* La boucle doit tourner tant que $i_sub_str est inférieur à $nbr_max_lignes. */ } while ($i_sub_str <= $nbr_max_lignes); /* Sinon on suit les autres instructions. */ } else { /* On affiche le texte sans coupure. */ echo $str; } echo '</p>';

Bah en fait... tu avais raison. Pas besoin d'un array. ^^
J'ai vachement simplifié le code :
Et voilà le résultat :

Que de code pour juste faire du bidouillage esthétique... mais bon, heureusement que PHP est là sinon on resterait limité avec CSS. Vivement qu'ils intègrent ce genre de possibilité dans les futurs versions de CSS.
J'ai encore 2 questions :
- Sais-tu comment récupérer un texte sur une autre page ? En fait le texte que je souhaite afficher serait la reprise du texte d'une actualité sur une autre page de mon site. Il faudrait donc que je puisse le récupérer automatiquement. Comme ça lorsque je publie une nouvelle actualité le texte serait automatiquement mis à jour sur l'index que tu peux voir sur l'image.
- Et sais-tu s'il y aurait moyen de justifier le texte affiché ? Parce que la méthode de l'ajout de span au début de chaque ligne est bien pour ensuite contrôler l'alignement gauche mais du coup je perds l'effet justifié du texte à droite. En fait c'est comme si le texte était juste aligné à gauche... Et les span sont les seules balises à ma connaissance pour marquer le début de chaque ligne.
J'ai vachement simplifié le code :
<?php /* On récupère la chaîne à couper et on l'intègre dans $str. */ $str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. FIN'; /* On définit le nombre de caractères de la première sous-chaîne et on l'enregistre dans $nbr_char_substr. */ $nbr_char_substr = 40; /* On débute l'affichage du paragraphe. */ echo '<p>'; /* Si le nombre total de caractères de la chaîne dépasse $nbr_char_substr on suit les instructions ci-dessous. */ if (strlen($str) > $nbr_char_substr) { /* On définit un index et on l'enregistre dans $i. */ $i = 1; /* On définit le point de départ de la première sous-chaîne et on l'enregistre dans $start. */ $start = 0; /* On définit le nombre maximum de sous-chaînes et on l'enregistre dans $nbr_substr. */ $nbr_substr = 19; /* On définit une valeur pour la marge gauche de la première sous-chaîne et on l'enregistre dans $marginleft. */ $marginleft = 0; /* On initialise une boucle. */ do { /* On coupe la chaîne à partir de $start jusqu'à $nbr_char_substr et on enregistre la sous-chaîne dans $substr. */ $substr = substr($str, $start, $nbr_char_substr); /* On recherche la position du dernier espace dans $substr et on l'enregistre dans $pos_esp. */ $pos_esp = strrpos($substr, ' '); /* On récupère le début de la sous-chaîne jusqu'à la position du dernier espace et on l'enregistre dans $start_substr. */ $start_substr = substr($substr, 0, $pos_esp); /* On supprime les éventuels espaces en début de sous-chaîne. */ $start_substr = ltrim($start_substr); /* On récupère la fin de la sous-chaîne à partir de la position du dernier espace et on l'enregistre dans $end_substr. */ $end_substr = substr($substr, $pos_esp); /* On définit le nombre de caractères dans $end_substr et on l'enregistre dans $nbr_char_end_substr. */ $nbr_char_end_substr = strlen($end_substr); /* S'il s'agit du dernier passage de la boucle on suit les instructions ci-dessous. */ if ($i == $nbr_substr) { /* On affiche la dernière sous-chaîne en ajoutant $end_last_substr à sa fin et en retirant le retour à la ligne. */ echo '<span style="margin-left: '.$marginleft.'%;">'.$start_substr.$end_last_substr.'</span>'; /* Sinon on suit les instructions ci-dessous. */ } else { /* On affiche normalement la sous-chaîne. */ echo '<span style="margin-left: '.$marginleft.'%;">'.$start_substr.'</span><br />'; } /* On incrémente $i de 1. */ $i++; /* On ajuste $start. */ $start = $start + $nbr_char_substr - $nbr_char_end_substr; /* S'il s'agit de l'avant-dernier passage de la boucle on suit les instructions ci-dessous. */ if ($i == ($nbr_substr - 1)) { /* On définit la fin de la dernière sous-chaîne et on l'enregistre dans $end_last_substr. */ $end_last_substr = '[...]'; /* On définit le nombre de caractères dans $end_last_substr et on l'enregistre dans $nbr_char_end_last_substr. */ $nbr_char_end_last_substr = strlen($end_last_substr); /* On incrémente $nbr_char_substr en prenant en compte le nombre de caractères dans $nbr_char_end_last_substr. */ $nbr_char_substr = $nbr_char_substr + 0.40 - $nbr_char_end_last_substr; /* Sinon on suit les instructions ci-dessous. */ } else { /* On incrémente normalement $nbr_char_substr. */ $nbr_char_substr = $nbr_char_substr + 0.40; } /* On décrémente $marginleft. */ $marginleft = $marginleft - 0.28; /* La boucle doit tourner tant que $i_substr est inférieur à $nbr_substr. */ } while ($i <= $nbr_substr); /* Sinon on suit les instructions ci-dessous. */ } else { /* On affiche la chaîne entière sans coupure. */ echo $str; } /* On termine l'affichage du paragraphe. */ echo '</p>'; ?>
Et voilà le résultat :

Que de code pour juste faire du bidouillage esthétique... mais bon, heureusement que PHP est là sinon on resterait limité avec CSS. Vivement qu'ils intègrent ce genre de possibilité dans les futurs versions de CSS.
J'ai encore 2 questions :
- Sais-tu comment récupérer un texte sur une autre page ? En fait le texte que je souhaite afficher serait la reprise du texte d'une actualité sur une autre page de mon site. Il faudrait donc que je puisse le récupérer automatiquement. Comme ça lorsque je publie une nouvelle actualité le texte serait automatiquement mis à jour sur l'index que tu peux voir sur l'image.
- Et sais-tu s'il y aurait moyen de justifier le texte affiché ? Parce que la méthode de l'ajout de span au début de chaque ligne est bien pour ensuite contrôler l'alignement gauche mais du coup je perds l'effet justifié du texte à droite. En fait c'est comme si le texte était juste aligné à gauche... Et les span sont les seules balises à ma connaissance pour marquer le début de chaque ligne.
justifier? aucune idée! à tout hasard: https://developer.mozilla.org/fr/docs/Web/CSS/text-justify
partager un texte entre deux pages? il me semble que cela implique de sauver quelque part ce texte sur ton site. par exemple dans un fichier ou une base de données.
comment le texte arrive-t'il sur le site?
partager un texte entre deux pages? il me semble que cela implique de sauver quelque part ce texte sur ton site. par exemple dans un fichier ou une base de données.
comment le texte arrive-t'il sur le site?
moi je ferais le travail en cherchant, pour chaque ligne, la position du dernier espace avant la longueur désirée pour cette ligne, ce qui permet de déterminer le contenu de la ligne, et de retirer ce contenu du texte restant à afficher.
https://www.php.net/manual/fr/function.strrpos.php
Le but c'est :
1 - Récupérer le texte
2 - Dire à PHP coupe le texte tous les X caractères, mais à chaque fois rajoute tant de caractères à X
OU (peut-être)
2 - Dire à PHP de jouer sur le padding-left, coupe le texte tous les X caractères, mais à chaque fois retire 0.5em au padding-left
3 - Afficher le texte
En fait l'idéal serait d'afficher d'abord le texte, de dire à PHP de lire le texte, et ensuite de travailler dessus... sauf que ce n'est pas ce que je veux faire. Je veux pouvoir travailler sur le texte avant de l'afficher.
1 - Récupérer le texte
2 - tant que texte n'est pas vide
- retirer les X premiers caractères du texte, et les ajouter à textefinal
- ajouter tant à X
3 - Afficher textefinal
ce serait plus clair si tu prenais un peu de temps pour présenter un exemple