web-dev-qa-db-fra.com

Le moyen le plus simple de "dessiner" des lignes simples sur une image avec jQuery et d'enregistrer dans Rails DB?

J'aimerais dessiner des lignes sur une image. Fondamentalement, permet à l'utilisateur de tracer un chemin pour les sentiers de montagne qu'il aime.

1) Quelqu'un connaît-il une bonne bibliothèque simple pour dessiner des lignes de base?

2) Après qu'un utilisateur dessine un tas de lignes sur une image, quelle serait la meilleure façon de sauvegarder les données dans la base de données?

25
Daniel Fischer

Tracer des lignes

Vous pouvez facilement superposer les éléments au-dessus d'une image pour que l'utilisateur dessine sur l'image.

Aussi, juste pour le plaisir, mais avez-vous vu SVG-edit ( demo )?

Sauvegarde des données de ligne

Le script SketchPad ci-dessus a fourni des données dessinées en JSON qui peuvent être enregistrées en texte brut dans la base de données. La même chose peut être faite sur les objets de PaperJS. Voici un JSFiddle exemple avec PaperJS ( code ) et ici avec une image en arrière-plan .

23
sirhc

Voici une solution rapide utilisant l'élément canvas et js standard (pas de bibliothèques) qui devrait vous aider à démarrer.

Ajoutez un élément canvas à votre page html.

<canvas id="canvas" width="800" height="600">
  Your browser does not support the canvas element.
</canvas>

Ajoutez du javascript pour dessiner votre image sur la toile. Il écoutera ensuite les clics et tracera les lignes lorsque l'utilisateur cliquera.

<script type="text/javascript">
  var canvas = document.getElementById("canvas");
  var context = document.getElementById('canvas').getContext('2d');

  var points = [];

  // Determine where the user clicked, I believe I pulled this from elsewhere on StackOverflow a while ago.
  function getCursorPosition(e) {
    var mx, my;
    if (e.pageX || e.pageY) {
      mx = e.pageX;
      my = e.pageY;
    }
    else {
      mx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
      my = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    mx -= canvas.offsetLeft;
    my -= canvas.offsetTop;
    return {x: mx, y: my};
  }

  // Once we have at least two points, draw a line between them.
  function drawPath() {
    context.beginPath();
    for (var i = 0; i < points.length - 1; i++) {
      context.moveTo(points[i]['x'], points[i]['y']);
      context.lineTo(points[i+1]['x'], points[i+1]['y']);
      context.stroke();
    }
    context.closePath();
  }

  // Listen for clicks, and redraw the map when they occur.
  function initPointCollection() {
    canvas.onclick = function(e) {
      var point = getCursorPosition(e);
      points.Push(point);

      if (points.length > 1) {
        drawPath();
      }
    }
  }

  function init() {
    // Load up your image.  Don't attempt to draw it until we know it's been loaded.
    var mountain = new Image();
    mountain.onload = function() {
      context.drawImage(this, 0, 0);
      initPointCollection();
    }
    mountain.src = 'mountain.png';  // Replace with actual image.
  }

  // Should check if document has finished loading first, but I'm too lazy, especially without JQuery.
  init();
</script>

J'ai réalisé que j'avais oublié de répondre à la deuxième moitié de la question, concernant l'enregistrement de l'image dans une base de données Rails. C'est plus difficile à répondre, car cela dépend de ce que vous voulez faire avec les données résultantes. Si vous voulez juste l'image finale, je vous suggère d'enregistrer l'image dans un système de fichiers (j'utilise S3 pour stocker toutes mes images) .Il y a une discussion sur la façon de le faire déjà sur StackOverflow: Capture HTML Canvas as gif/jpg/png/pdf?

Si vous avez besoin de manipuler le chemin tracé, je voudrais enregistrer les points de données individuels ainsi qu'une référence à l'image sous-jacente. Renvoyez les points de données à votre Rails serveur via ajax, avec l'url de votre image. Votre table de base de données peut alors ressembler à ceci:

create_table :hiking_paths do |t|
  t.string 'image_url', :null => false
  t.string 'points', :limit => 1000  #if you want unlimited points, change to text column type
  t.timestamps
end
6
Evan Pon

html5 canvas est la seule chose que je connaisse qui vous permettrait de faire cela. Voici un excellent article à ce sujet: http://diveintohtml5.info/canvas.html

3
Trav McKinney