Draw with poetry (french)

In this example below you will see how to do a Draw with poetry (french) with some HTML / CSS and Javascript

Click and drag to draw a poem using your mouse, change the text if you want, add some colours, use your imagination and then save it. The poem here is Les Djinns, by french writer Victor Hugo. Interface and comments in french.

Thumbnail
This awesome code was written by tibomahe, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright tibomahe ©

Technologies

  • HTML
  • CSS
  • JavaScript
      <div id='editControls'>
      <a class='btn' data-role='#e63157' href='#'>rouge</a>
      <a class='btn' data-role='#235e75' href='#'>bleu</a>
      <a class='btn' data-role='#ffd56c' href='#'>jaune</a>
      <a class='btn' data-role='#80ccad' href='#'>vert</a>
      <a class='btn' data-role='black' href='#'>noir</a>
      <a class='btn' id="modify" href='#'>Modifier le texte</a>
      <input class='btn' id="submit" type="submit" value="Sauvegarder"/>
  </div> <!-- /. #editControls -->

  <p>Cliquez et glissez le curseur pour dessiner le texte. Double-cliquer pour effacer la page.</p>


  <canvas id='canvas'></canvas>
  
  <span id='nettoyage'>Nettoyé !</span>

  <div id="modal">
    <div id="select-strophe">Sélectionnez une strophe du poème Les Djins de Victor Hugo</div>
    <div class="btn-group1">
      <a class='btn' data-role="letters1" href='#'>1</a>
      <a class='btn' data-role="letters2" href='#'>2</a>
      <a class='btn' data-role="letters3" href='#'>3</a>
      <a class='btn' data-role="letters4" href='#'>4</a>
      <a class='btn' data-role="letters5" href='#'>5</a>
      <a class='btn' data-role="letters6" href='#'>6</a>
      <a class='btn' data-role="letters7" href='#'>7</a>
      <a class='btn' data-role="letters8" href='#'>8</a>
      <a class='btn' data-role="letters9" href='#'>9</a>
      <a class='btn' data-role="letters10" href='#'>10</a>
      <a class='btn' data-role="letters11" href='#'>11</a>
      <a class='btn' data-role="letters12" href='#'>12</a>
      <a class='btn' data-role="letters13" href='#'>13</a>
      <a class='btn' data-role="letters14" href='#'>14</a>
      <a class='btn' data-role="letters15" href='#'>15</a>
    </div>
  	<div id="pres">Ou proposez votre propre texte : plusieurs phrases sont possibles, mais pas de retour à la ligne ni de texte pré-formaté (copier-coller notamment).</div>
	  <div id="edit" contenteditable>
	  	Remplacez-moi par votre message !
	  </div>
	  <div class="btn-group2">
		  <a class='btn' id="delete" href='#'>Annuler</a>
		  <a class='btn' id="finish" href='#'>Terminer !</a>
		</div>
  </div> <!-- /. #modal -->

<script src='https://code.jquery.com/jquery-2.1.1.min.js'></script>
<script src="https://raw.githubusercontent.com/eligrey/Blob.js/master/Blob.js"></script>
<script src="https://raw.githubusercontent.com/eligrey/canvas-toBlob.js/master/canvas-toBlob.js"></script>
<script src="https://raw.githubusercontent.com/eligrey/FileSaver.js/master/FileSaver.js"></script>

/*Downloaded from https://www.codeseek.co/tibomahe/draw-with-poetry-french-wDern */
    
/* ---------------------------------------------------------------- */
    /* GENERAL */
/* ---------------------------------------------------------------- */

html, body {
  width: 100%;
  height: 100%;
  margin: 0px;
  overflow: hidden;
}
canvas {
  cursor: crosshair;
  z-index:10; 
  margin-top:0;
}
span#nettoyage { 
  display:none; 
  font-family: 'Georgia', cursive;
  font-size: 40px;
  position: fixed;
  top: 50%;
  left: 50%;
  color: #000;
  margin-top: -40px;
  margin-left: -80px; 
}

/* ---------------------------------------------------------------- */
    /* BOUTONS DE L'INTERFACE */
/* ---------------------------------------------------------------- */

p {
  z-index:-10;
  top:5px;
  left:300px;
  position:fixed;
}
#editControls {
  top:15px;
  left:10px;
  z-index:20;
  position:fixed;
}
#editControls .btn {
  text-decoration:none;
  border:1px solid silver;
  border-radius:5px;
  box-shadow: inset 0 0 10px silver;
  background: white;
  margin: 0 auto;
  padding:10px;
}
#editControls .btn:hover {
  cursor:pointer;
}
#editControls .btn:nth-child(1) {
  background-color: #e63157;
  color:#DDD;
}
#editControls .btn:nth-child(2) {
  background-color: #235e75;
  color:#CCC;
}
#editControls .btn:nth-child(3) {
  background-color: #ffd56c;
  color:#666;
}
#editControls .btn:nth-child(4) {
  background-color: #80ccad;
  color:#666;
}
#editControls .btn:nth-child(5) {
  background-color: black;
  color:#DDD;
}
#editControls #modify {
  right:10px;
  position:fixed;
  top:5px;
  color:black;
}
#editControls #submit {
  right:10px;
  position:fixed;
  top:50px;
  color:black;
}

/* ---------------------------------------------------------------- */
    /* BOÎTE MODALE (POP IN) */
/* ---------------------------------------------------------------- */


#modal {
  width:500px;
  min-height:400px;
  position:fixed;
  top:20px;
  margin-right:50%;
  right:-2500px;
  z-index:50;
  border:1px solid silver;
  border-radius:5px;
  box-shadow: inset 0 0 10px silver;
  background: white;
  transition: all 0.5s linear 0s;
}
#pres, #select-strophe {
  padding:10px 10px;
  font-style: italic;
}
#edit {
  min-height:190px;
  border:1px solid black;
  margin:10px;
  border-radius:5px;
  padding:5px;
}
#modal .btn-group1 .btn {
  text-decoration:none;
  border:1px solid silver;
  border-radius:5px;
  box-shadow: inset 0 0 10px silver;
  background: grey;
  padding:5px;
  color:white;
  width:20px;
  margin:0;
  float:left; 
  text-align:center;
}

#modal .btn-group1:after {
   content: " "; 
   visibility: hidden;
   display: block;
   height: 0;
   clear: both;
}
#modal .btn-group1 {
    margin:0 0 0 10px;
}
#modal .btn-group1 .btn.selected {
  background: black;
}
#modal .btn-group2 {
    margin:20px 0 0 300px;
}
#modal .btn-group2 .btn {
  text-decoration:none;
  border:1px solid silver;
  border-radius:5px;
  box-shadow: inset 0 0 10px silver;
  background: grey;
  padding:10px;
  color:white;
}
#modal .btn-group2 .btn:nth-child(1) {   
  background: white;
  color:grey;
}


/*Downloaded from https://www.codeseek.co/tibomahe/draw-with-poetry-french-wDern */
    /* Ce script utilise https://codepen.io/tholman/pen/qCnfB. Le code est commenté sur https://github.com/tibomahe/dessiner-avec-poesie.*/


var letters1 = "Murs, ville Et port, Asile De mort, Mer grise Où brise La brise, Tout dort.";
var letters2 = "Dans la plaine Naît un bruit, C'est l'haleine De la nuit. Elle brame Comme une âme Qu'une flamme Toujours suit.";
var letters3 = "La voix plus haute Semble un grelot. – D'un nain qui saute C'est le galop : Il fuit, s'élance, Puis en cadence Sur un pied danse Au bout d'un flot.";
var letters4 = "La rumeur approche ; L'écho la redit. C'est comme la cloche D'un couvent maudit ; – Comme un bruit de foule, Qui tonne et qui roule, Et tantôt s'écroule Et tantôt grandit,";
var letters5 = "Dieu ! la voix sépulcrale Des Djinns ! – Quel bruit ils font ! Fuyons sous la spirale De l'escalier profond ! Déjà, s'éteint ma lampe, Et l'ombre de la rampe, Qui le long du mur rampe, Monte jusqu'au plafond.";
var letters6 = "C'est l'essaim des Djinns qui passe, Et tourbillonne en sifflant.Les ifs, que leur vol fracasse, Craquent comme un pin brûlant ; Leur troupeau, lourd et rapide, Volant dans l'espace vide, Semble un nuage livide Qui porte un éclair au flanc.";
var letters7 = "Ils sont tout près ! – Tenons fermée Cette salle où nous les narguons. Quel bruit dehors ! hideuse armée De vampires et de dragons ! La poutre du toit descellée Ploie ainsi qu'une herbe mouillée, Et la vieille porte rouillée Tremble, à déraciner ses gonds !";
var letters8 = "Cris de l'enfer ! voix qui hurle et qui pleure ! L'horrible essaim, poussé par l'aquilon, Sans doute, ô ciel ! s'abat sur ma demeure. Le mur fléchit sous le noir bataillon. La maison crie et chancelle, penchée, Et l'on dirait que, du sol arrachée, Ainsi qu'il chasse une feuille séchée, Le vent la roule avec leur tourbillon !";
var letters9 = "Prophète ! si ta main me sauve De ces impurs démons des soirs, J'irai prosterner mon front chauve Devant tes sacrés encensoirs ! Fais que sur ces portes fidèles Meure leur souffle d'étincelles, Et qu'en vain l'ongle de leurs ailes Grince et crie à ces vitraux noirs !";
var letters10 = "Ils sont passés ! – Leur cohorte S'envole, et fuit, et leurs pieds Cessent de battre ma porte De leurs coups multipliés. L'air est plein d'un bruit de chaînes, Et, dans les forêts prochaines, Frissonnent tous les grands chênes, Sous leur vol de feu pliés !";
var letters11 = "De leurs ailes lointaines Le battement décroît, Si confus dans les plaines, Si faible, que l'on croit Ouïr la sauterelle Crier d'une voix grêle, Ou pétiller la grêle Sur le plomb d'un vieux toit.";
var letters12 = "D'étranges syllabes Nous viennent encor ; – Ainsi des Arabes Quand sonne le cor, Un chant sur la grève Par instants s’élève, Et l'enfant qui rêve Fait des rêves d'or !";
var letters13 = "Les Djinns funèbres, Fils du trépas, Dans les ténèbres Pressent leurs pas ; Leur essaim gronde : Ainsi, profonde, Murmure une onde Qu'on ne voit pas.";
var letters14 = "Ce bruit vague Qui s'endort, C'est la vague Sur le bord ; C'est la plainte, Presque éteinte, D'une sainte Pour un mort.";
var letters15 = "On doute La nuit… J'écoute : – Tout fuit, Tout passe ; L'espace Efface Le bruit.";
var letters = letters1 ;
var counter = 0;
var minFontSize = 3;
var angleDistortion = 0;
var letter = letters[counter];
var textColor = 'black' ;
var canvas;
var context;
var mouse = {
  x: 0, 
  y: 0, 
  write: false
};
var position = {
  x:0,
  y: 0
};
//console.log(letters);

$('.btn-group1 a').click(function() {
  if ($(this).hasClass( "selected" )) { 
    $(this).removeClass("selected"); 
    $('#edit').html('Remplacez-moi par votre message !');
  }
  else { 
    $('.btn-group1 a').removeClass("selected"); 
    $(this).addClass("selected");
    letters = window[$('.btn-group1 a.selected').data('role')];
    $('#edit').html(letters); 
  };
});

$('a#finish').click(function() {
     counter = 0;
     letters = $('#edit').html() + ' '; 
     minFontSize = 3;
     angleDistortion = 0;
     letter = letters[counter];
     console.log(letters);
     $('#modal').css("z-index", "-200");
     $('#modal').css("right", "-2500px");
});

$("#submit").click(function(e) {
  e.preventDefault();
  canvas.toBlob(function(blob) { 
    saveAs(blob, "foo_from_canvas.png"); 
  });
});

function init() {
  canvas = document.getElementById( 'canvas' );
  context = canvas.getContext( '2d' );
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  canvas.addEventListener('mousemove', mouseMove, false);
  canvas.addEventListener('mousedown', mouseDown, false);
  canvas.addEventListener('mouseup',   mouseUp,   false);
  canvas.addEventListener('mouseout',  mouseUp,  false);  
  canvas.addEventListener('dblclick', doubleClick, false);
}

function mouseMove (e){
  mouse.x = e.pageX;
  mouse.y = e.pageY;
  draw();
  $('#nettoyage').hide();
}

function mouseDown(e){
  mouse.write = true;
  position.x = e.pageX;
  position.y = e.pageY;  
  $('#editControls').css("z-index", "-10");
}

function mouseUp(e){
    mouse.write = false;
    $('#editControls').css("z-index", "20");
}

function doubleClick(e) {
  $('#nettoyage').show();
  canvas.width = canvas.width; 
}

function draw() {
 if ( mouse.write ) {
    var d = distance( position, mouse ); 
    var fontSize = minFontSize + d/4; 
    var letter = letters[counter];
    var stepSize = textWidth( letter, fontSize );
    
    if (d > stepSize) {

      var angle = Math.atan2(mouse.y-position.y, mouse.x-position.x);
      context.font = fontSize + "px Georgia";
      context.fillStyle = textColor;
      context.save();
      context.translate( position.x, position.y);
      context.rotate( angle );
      context.fillText(letter,0,0);
      context.restore();
      counter++;
      if (counter > letters.length-1) {
        counter = 0;
      }    
    //console.log (position.x + Math.cos( angle ) * stepSize)
      position.x = position.x + Math.cos(angle) * stepSize;
      position.y = position.y + Math.sin(angle) * stepSize;

      }
  }     
}

function distance( a, b ){
  var xs = 0;
  var ys = 0;
  xs = b.x - a.x;
  xs2 = xs * xs;
  ys = b.y - a.y;
  ys2 = ys * ys;
  return Math.sqrt( xs2 + ys2 );
};

function textWidth( string, size ) {
  context.font = size + "px Georgia";
  if ( context.fillText ) {
    return context.measureText( string ).width;
  } else if ( context.mozDrawText) {
    return context.mozMeasureText( string );
  }
  
};

$('#editControls a').click(function() {
    textColor = $(this).data('role');
});

$('a#modify').click(function() {
  var foo = $('#modal').css("right");
  if ( foo == "-250px") { 
    $('#modal').css("z-index", "-200");
    $('#modal').css("right", "-2500px");
  }
  else { 
    $('#modal').css("z-index", "200");
    $('#modal').css("right", "-250px");
  }
});

$('a#delete').click(function() { 
     $('#modal').css("z-index", "-200");
     $('#modal').css("right", "-2500px");
});

init();



Comments