Easiest way to “draw” simple lines over an image w

2019-03-09 09:05发布

I'd like to draw lines on an image. Basically allow the user to draw a path for mountain trails they like.

1) Does anyone know a good simple library for drawing basic lines?

2) After a user draws a bunch of lines on an image, what would be the best way to save the data to the database?

3条回答
爷、活的狠高调
2楼-- · 2019-03-09 09:53

Here's a quick solution using the canvas element and regular js (no libraries) that should help you get started.

Add a canvas element to your html page.

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

Add javascript to draw your image on the canvas. It will then listen for clicks, and draw the lines as the user clicks.

<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>

Realized I forgot to answer the second half of the question, regarding saving the image to a Rails DB. This is harder to answer, because it depends on what you want to do with the resulting data. If you just want the final image, I suggest you save the image to a filesystem (I use S3 to store all my images). There's a discussion on how to do this already on StackOverflow: Capture HTML Canvas as gif/jpg/png/pdf?

If you need to manipulate the path drawn, I would save the individual data points as well as a reference to the underlying image. Send the datapoints back to your Rails server via ajax, along with the url of your image. Your database table may then look something like this:

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
查看更多
唯我独甜
3楼-- · 2019-03-09 09:56

html5 canvas is the only thing I know that would allow you to do this. Here is a great article on it: http://diveintohtml5.info/canvas.html

查看更多
贼婆χ
4楼-- · 2019-03-09 10:01

Drawing lines

You can easily overlay the elements on top of an image so the user draws on the image.

Also, just for fun, but have you seen SVG-edit (demo)?

Saving the line data

The SketchPad script above provided drawn data in JSON that can be saved as plain text in the database. The same thing can be done on the objects from PaperJS. Here is a JSFiddle example with PaperJS (code) and here with an image as a background.

查看更多
登录 后发表回答