//容器ID,宽度,高度
var r = Raphael("draw", 620, 420),
circleAttr = {fill: "#ccc", stroke: "#999"},
radius = 5,
//当前移动的id,方便及时更新points数组信息
changeID = 0,
//移动两条线的节点的时候无需改变ox,oy值
//移动一根线的时候需要变
oPointNoChange = false,
_path = [],
curves = [],
points = [],
circles = [],
controls = [],
_rect = document.getElementById("draw");
//绘制矩形
//x,y,宽度,高度,边角弧度(radius属性)
r.rect(0,0,619,419,10).attr({stroke:"#666"});
r.text(310, 20, "Drag the points to change the curves").attr({fill: "#666", "font-size": 16});
//上一个坐标x,y值;当前坐标x,y值
var ox,oy,nx,ny,
moving = false;
function curve(_x,_y){
var _temp;
if(!ox && !oy){
ox = _x,oy=_y;
//画圆,坐标x,y,半径
_temp = r.circle(ox,oy,radius).attr(circleAttr);
//保存
circles.push(_temp);
controls = r.set(circles);
//保存坐标
points.push({"x":_x,"y":_y,"id":_temp.id});
}else if(ox && oy){
nx = _x,ny=_y;
_path = [["M",ox,oy],["L",nx,ny]];
_temp = r.circle(nx,ny,radius).attr(circleAttr);
//保存
circles.push(_temp);
//画线,保存
curves.push(r.path(_path).attr({"color":"hsb(.1, .75, .75)","stroke-width": 2,"stroke-linecap": "round"}));
//坐标,保存,id
points.push({"x":nx,"y":ny,"id":_temp.id});
//画圈,保存
controls = r.set(circles);
}
var len = points.length-1;
//2个节点
if(len === 1){
controls[0].update = function(x,y){
if(!curves.length)return;
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({cx: X, cy: Y});
//自身的坐标
_path[0][1] = X;
_path[0][2] = Y;
//线另一端节点的坐标
_path[1][1] = points[1].x
_path[1][2] = points[1].y
curves[0].attr({path:_path});
oPointNoChange = true;
}
//会被新增节点的update方法覆盖
controls[1].update = function(x,y){
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({cx: X, cy: Y});
//原点的坐标
_path[0][1] = points[0].x;
_path[0][2] = points[0].y;
//自身移动的坐标
_path[1][1] = X;
_path[1][2] = Y;
curves[0].attr({path:_path});
oPointNoChange = false;
}
}else if(len >1){//多个节点
var _len = len -1,
oPath = [];
//最新节点移动
controls[len].update = function(x,y){
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({cx: X, cy: Y});
//上一个节点的坐标
_path[0][1] = points[_len].x;
_path[0][2] = points[_len].y;
//当前坐标
_path[1][1] = X;
_path[1][2] = Y;
curves[len-1].attr({path:_path});
oPointNoChange = false;
}
//连接两条线跟着移动
controls[_len].update = function(x,y){
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({cx: X, cy: Y});
//当前坐标
_path[0][1] = X;
_path[0][2] = Y;
//下一个节点的坐标
_path[1][1] = points[len].x;
_path[1][2] = points[len].y;
//起始点变,终点不变
curves[_len].attr({path:_path});
oPath = [["M",points[_len-1].x,points[_len-1].y],["L",X,Y]];
//终点变,起始点不变
curves[_len-1].attr({path:oPath});
oPointNoChange = true;
}
}
controls.drag(move,start,up);
if(nx && ny){
ox = nx,oy = ny;
}
}
//参数:x,y值的位移,递增
function move(dx, dy) {
this.update(dx - (this.dx || 0), dy - (this.dy || 0));
this.dx = dx;
this.dy = dy;
}
//开始移动
//记录移动节点的id信息
function start() {
this.dx = this.dy = 0;
moving = true;
changeID = this.id;
}
function up() {
//更新最新的节点坐标
//移动新节点的时候更新
if(!oPointNoChange){
ox = this.dx+ox;
oy = this.dy+oy;
}
//更新points数组对应坐标信息
if(changeID){
for(var i=0,l=points.length; i<l ;i++){
if(points[i].id == changeID){
points[i].x = this.attr("cx");
points[i].y = this.attr("cy");
break;
}
}
}
}
_rect.onclick = function(e){
var e = e || window.event;
if(!moving){
curve(e.offsetX,e.offsetY);
}
moving = false;
}
<div id="draw">
</div>
#draw{height: 480px;position: absolute;width: 640px;left:0;top:0;}