用raphael javascript移动多个元素

时间:2015-01-22 21:19:08

标签: javascript svg raphael

我正在使用Raphael javascript基于Raphael网站上给出的一个示例(曲线示例)为CMS创建图像标记功能。它的工作原理是让用户向图像添加箭头(路径)和标签(文本)并移动它们以标记图像中的结构(“兴趣点”)。我已经让它适用于一条路径pr。标签(jsfiddle.net/nartex1234/9m5d7fqd/),但努力使其适用于多个路径pr。标签(jsfiddle.net/nartex1234/wm1odgtz/)。

我觉得这一切都归结为我编程技巧的极限。我真的不知道如何掌握解决方案。我已经包含了下面工作示例的代码。任何关于如何使这项工作的建议或提示都是最受欢迎的。

// Create canvas
var R = Raphael(0, 0, "100%", "100%");

// This is the style objects for the article labels
var labelattr = {
  font: "30px Helvetica",
  "font-weight": "bold",
  opacity: 0.9,
  fill: "#fff",
  "stroke-width": 1,
  stroke: "#000"
};

var discattr = {
  fill: "#f0f",
  stroke: "none",
  opacity: 0.3 // normaly set to 0.01 so that it is not visible
};

var arrowattr = {
  "stroke-width": 3,
  "stroke-linecap": "round",
  "arrow-end": "classic -wide"
};

// The JSON data object (normally provided via AJAX from a database)
var data = [{
  "label": "Red",
  "articlelabelid": "12",
  "labelid": "28",
  "x1": "400",
  "y1": "150",
  "pois": [{
    "articlelabelid": "12",
    "poid": "3",
    "x2": "300",
    "y2": "400"
  }]
}, {
  "label": "Yellow",
  "articlelabelid": "13",
  "labelid": "30",
  "x1": "300",
  "y1": "500",
  "pois": [{
    "articlelabelid": "13",
    "poid": "4",
    "x2": "400",
    "y2": "600"
  }, {
    "articlelabelid": "13",
    "poid": "5",
    "x2": "450",
    "y2": "600"
  }, {
    "articlelabelid": "13",
    "poid": "6",
    "x2": "200",
    "y2": "500"
  }]
}, {
  "label": "Blue",
  "articlelabelid": "14",
  "labelid": "29",
  "x1": "700",
  "y1": "450",
  "pois": [{
    "articlelabelid": "14",
    "poid": "13",
    "x2": "900",
    "y2": "800"
  }, {
    "articlelabelid": "14",
    "poid": "14",
    "x2": "800",
    "y2": "700"
  }]
}, {
  "label": "Black",
  "articlelabelid": "15",
  "labelid": "31",
  "x1": "100",
  "y1": "100",
  "pois": [{
    "articlelabelid": "15",
    "poid": "15",
    "x2": "200",
    "y2": "200"
  }]
}];


// The start, move and up functions
function start() {}

function move(dx, dy) {
  this.update(dx - (this.dx || 0), dy - (this.dy || 0));
  this.dx = dx;
  this.dy = dy;
}

function up() {
  this.dx = this.dy = 0;
  switch (this.type) {
    case "text":
      x = this.attr("x"), y = this.attr("y"), objclass = 'articlelabel_' + this.node.id;
      break;
    case "circle":
      x = this.attr("cx"), y = this.attr("cy"), objclass = 'poi_' + this.node.id;
      break;
  }
}



// Function to draw the labels and lines, but only the first line/poi (point of interest) in the object
function labeline(object) {
  // Find coordinates of label
  var x = parseInt(object.x1, 10);
  var y = parseInt(object.y1, 10);
  // Number of pois (points of interest) for this label
  var poi_count = Object.keys(object.pois).length;

  var ax = parseInt(object['pois'][0]['x2'], 10);
  var ay = parseInt(object['pois'][0]['y2'], 10);
  var label = object.label;
  var articlelabelid = object.articlelabelid;
  var poid = object['pois'][0]['poid'];

  // The path - creates an array with two arrays within it
  var path = [
      ["M", x, y],
      ["L", ax, ay]
    ],


    // The set
    controls = R.set(
      R.path(path).attr(arrowattr), // Controls [0]
      R.circle(ax, ay, 9).attr(discattr), // Controls [1]
      R.text(x, y, label).attr(labelattr) // Controls [2]
    );

  controls[2].update = function(x, y) {
    this.node.id = articlelabelid;
    var X = this.attr("x") + x,
      Y = this.attr("y") + y;
    this.attr({
      x: X,
      y: Y
    });
    path[0][1] = X;
    path[0][2] = Y;
    controls[0].attr({
      path: path
    });
  };
  controls[1].update = function(x, y) {
    this.node.id = poid;
    var X = this.attr("cx") + x,
      Y = this.attr("cy") + y;
    this.attr({
      cx: X,
      cy: Y
    });
    path[1][1] = X;
    path[1][2] = Y;
    controls[0].attr({
      path: path
    });
  };
  controls.drag(move, start, up);
}

// Run function for every label in the JSON data object
for (var i = 0; i < data.length; i++) {
  labeline(data[i]);
}

1 个答案:

答案 0 :(得分:0)

我找到了解决方案也许不是最优雅的解决方案,但它确实有效。这一切都归结为每个点使用for循环。我已将此脚本与我的CMS集成,现在它的工作方式应该如此(在数据库中添加和保存标签和箭头位置)。如果有人发现它有用,我会包含该脚本。 Heres是更新的JS Fiddle http://jsfiddle.net/nartex1234/wm1odgtz/

// Create canvas
var R = Raphael(0, 0, "100%", "100%");

// This is the style objects for the article labels
var labelattr = {
    font: "30px Helvetica",
        "font-weight": "bold",
    opacity: 0.9,
    fill: "#fff",
        "stroke-width": 1,
    stroke: "#000"
};

var discattr = {
    fill: "#f0f",
    stroke: "none",
    opacity: 0.3 // normaly set to 0.01 so that it is not visible
};

var arrowattr = {
    "stroke-width": 3,
        "stroke-linecap": "round",
        "arrow-end": "classic -wide"
};

// The JSON data object (normally provided via AJAX from a database)
var data = [{
    "label": "Red",
        "articlelabelid": "12",
        "labelid": "28",
        "x1": "400",
        "y1": "150",
        "pois": [{
        "articlelabelid": "12",
            "poid": "3",
            "x2": "300",
            "y2": "400"
    }]
}, {
    "label": "Yellow",
        "articlelabelid": "13",
        "labelid": "30",
        "x1": "300",
        "y1": "500",
        "pois": [{
        "articlelabelid": "13",
            "poid": "4",
            "x2": "400",
            "y2": "600"
    }, {
        "articlelabelid": "13",
            "poid": "5",
            "x2": "450",
            "y2": "600"
    }, {
        "articlelabelid": "13",
            "poid": "6",
            "x2": "200",
            "y2": "500"
    }]
}, {
    "label": "Blue",
        "articlelabelid": "14",
        "labelid": "29",
        "x1": "700",
        "y1": "450",
        "pois": [{
        "articlelabelid": "14",
            "poid": "13",
            "x2": "900",
            "y2": "800"
    }, {
        "articlelabelid": "14",
            "poid": "14",
            "x2": "800",
            "y2": "700"
    }]
}, {
    "label": "Black",
        "articlelabelid": "15",
        "labelid": "31",
        "x1": "100",
        "y1": "100",
        "pois": [{
        "articlelabelid": "15",
            "poid": "15",
            "x2": "200",
            "y2": "200"
    }]
}];


// The start, move and up functions
function start() {}

function move(dx, dy) {
    this.update(dx - (this.dx || 0), dy - (this.dy || 0));
    this.dx = dx;
    this.dy = dy;
}

function up() {
    this.dx = this.dy = 0;
    switch (this.type) {
        case "text":
            x = this.attr("x"), y = this.attr("y")
            break;
        case "circle":
            x = this.attr("cx"), y = this.attr("cy")
            break;
    }
}

// Make array of all paths and circles
function pointers(count, object, x, y) {
    var pointers = [];
    for (var i = 0; i < count; i++) {
        var ax = parseInt(object.pois[i].x2, 10);
        var ay = parseInt(object.pois[i].y2, 10);
        pointers[i] =
            [
                [ax, ay, 9],        /*POI [0] */    
                [                   /*PATH [1] */
                    ["M", x, y],
                    ["L", ax, ay]
                ]
            ]                   
        }
    return pointers;
}




// This works for one pois pr. label, but not multiple pois pr label or labels without poi
function labeline(object) {
    // Find coordinates of label
    var x = parseInt(object.x1, 10);
    var y = parseInt(object.y1, 10);
    // Number of pois (points of interest) for this label
    var poi_count = Object.keys(object.pois).length;

    // Label variables from objevt
    var label = object.label;
    var articlelabelid = object.articlelabelid;

    // Make array of all paths and circles
    var result = pointers(poi_count, object, x, y);

    // Makes new arrays for paths and controls
    var path = [];
    var controls = [];  

    for (var i = 0; i < result.length; i++) {
        // Adds paths to the path array
        path[i] = result[i][1];

        // The set
        controls[i] = R.set(
            R.path(path[i]).attr(arrowattr), // Controls [0]
            R.circle(result[i][0][0], result[i][0][1], result[i][0][2]).attr(discattr)//, // Controls [1]
        );
        // Sets the key of the controls as a 'parentkey' property of the child array and the id of the point of interest as the node id
        controls[i][1].parentkey = i;
        controls[i][1].node.id = 'poi_' + object.pois[i].poid;

        // Updating the correct path
        controls[i][1].update = function (x, y) {
            var X = this.attr("cx") + x,
                Y = this.attr("cy") + y;
            this.attr({
                cx: X,
                cy: Y
            });
            path[this.parentkey][1][1] = X;
            path[this.parentkey][1][2] = Y;
            controls[this.parentkey][0].attr({
                path: path[this.parentkey]
            });
        };
        controls[i].drag(move, start, up);      
    }

    // The label
    label = R.text(x, y, label).attr(labelattr);
    label.node.id = 'articlelabel_' + articlelabelid;
    label.update = function (x, y) {
        var X = this.attr("x") + x,
            Y = this.attr("y") + y;
        this.attr({
            x: X,
            y: Y
        });
        for (var i = 0; i < path.length; i++) {
            path[i][0][1] = X;
            path[i][0][2] = Y;
            controls[i][0].attr({
                path: path[i]
            });
        }
    };
    label.drag(move, start, up);
}

// Run function for every label in the JSON data object
for (var i = 0; i < data.length; i++) {
    labeline(data[i]);
}