0

我有很多年的编码经验,但很少有 javascript 和 raphael。我一直在网上找一本我在拉斐尔买的书。我正在尝试做的部分事情是拥有一条线/路径,并为用户提供向这条线添加或编辑点的能力。类似于谷歌地图上的路线。

我知道可以使用数组构建路径。我相信这些元素可以有一个唯一的 id,这将有助于访问它们。

我正在考虑类似于此问题中建议的一种方法,特别是 Adam Moszczyński 将绘图与数据分离的方法;特别是在路上,很可能需要持久化/加载此路径数据。

4

1 回答 1

1

如果您只想绘制直线,那么 SVG 路径语法相当简单。您实际上只需要知道两个命令:M设置路径上第一个点的位置,并L在其余点上画一条线。

例如,要绘制以下折线:

       [5,2]___________[12,2]
        /                 \
       /                   \
      /                   [13,5]
     /
 [1,10]

您将使用以下 SVG 路径:

M 1 10 L 5 2 L 12 2 L 13 5

请注意,SVG 接受,数字分隔符,命令和参数之间的空格是可选的,如果它们是明确的。所以上面的路径也可以写成:

M 1,10 L 5,2 L 12,2 L 13,5

甚至:

M1,10L5,2L12,2L13,5

但是第一种形式是最方便我们以编程方式使用的,因为它可以简单地通过将数组元素与空格字符连接起来来构造:

var svgpath = [
    'M', 1, 10,
    'L', 5, 2,
    'L', 12, 2,
    'L', 13, 5
].join(' ');

鉴于此,很容易编写一个在 Raphael 中绘制路径的函数。有两种方法可以做到这一点:

  1. 编写自己独立的线描函数/库,并使用 Raphael 作为工具在屏幕上绘图。最简单的只是一个绘制折线的函数。

    function draw_polyline(paper,coords) {
      var first = coords.shift();
      var path = ['M', first[0], first[1]];
      for (var i=0; i<coords.length; i++) {
        path.push('L',coords[i][0],coords[i][1]);
      }
      return paper.path(path.join[' ']);
    }
    
    draw_polyline(paper,[[1,10],[5,2],[12,2],[13,5]]);
    
  2. 把它写成 Raphael 的扩展。该函数完全相同,但表现得好像它是 Raphael 的一部分:

    Raphael.fn.polyline = function (coords) {
      var first = coords.shift();
      var path = ['M', first[0], first[1]];
      for (var i=0; i<coords.length; i++) {
        path.push('L',coords[i][0],coords[i][1]);
      }
      return this.path(path.join[' ']);
    }
    
    var paper = Raphael('div',640,480);
    paper.polyline([[1,10],[5,2],[12,2],[13,5]]);
    

请注意,上面的简单函数只是从给定坐标绘制直线。要向直线添加或删除点,您必须通过使用更新的坐标调用折线函数来重绘路径。这可行,但并不完全理想,因为您必须跟踪旧线并在绘制新线时将其删除。

更好的解决方案是让生产线自行更新。为此,我们需要重构上面的代码,将 svg 路径生成与绘图函数分开:

function polyline_path(coords) {
  var first = coords.shift();
  var path = ['M', first[0], first[1]];
  for (var i=0; i<coords.length; i++) {
    path.push('L',coords[i][0],coords[i][1]);
  }
  return path.join(' ');
}

那么 Raphael 的实现很简单:

Raphael.fn.polyline = function (coords) {
  return this.path(polyline_path(coords));
}

现在我们可以向代表折线的 Raphael 路径对象添加一些功能:

Raphael.fn.polyline = function (coords) {
  var path = this.path(polyline_path(coords));
  path.coords = function(xy) {
    if (!xy) {return coords} // return coordinates if no arguments given

    coords = xy;
    path.attr('path',polyline_path(coords)); // otherwise update svg path
  }
  return path;
}

现在我们可以像这样使用它:

var route = paper.polyline([[1,10],[5,2],[12,2],[13,5]]);

// Add point to route:
route.coords(route.coords().push([15,10]));

这仍然有点笨拙,但你明白了。您可以使用这个基本概念来实现更高级的 API。例如,如果折线对象实现了大多数 Array 方法,那就太好了,这样您就可以简单地执行以下操作:

route.push([15,10]); // add point to route
route.shift(); // remove point from beginning of route
route.splice(1,1,[5,3]); // modify the second point
// etc..

你想走多远真的取决于你。

于 2013-10-17T04:46:07.177 回答