您的位置:首页 > Web前端 > JavaScript

Raphaël的动态线条添加,节点拖拽

2017-01-20 10:15 260 查看
大部分参考:原文地址

http://www.cnblogs.com/liulun/archive/2012/05/18/2507472.html?utm_source=tuicool&utm_medium=referral

首先定义几个变量:

var paper =null;

var dragger=null;

var move=null;

var up=null;

var shapes=null;

var mouseX=null;//存储页面中鼠标的X轴坐标

var mouseY=null;//存储页面中鼠标的Y轴坐标

var r=null;

var objCrr=null;

var mouse=null;//存储页面中鼠标的属性

var connections=[];//用来存储节点的顺序

$(function(){

$("#holder").mousemove(function(obj){

moush=obj;

moushX=obj.clientX;

moushY=obj.clientY;

if(objCrr!=null){

r.drawArr(objCrr);

}

})

//拖动节点开始时的事件

            var dragger = function () {

                this.ox = this.attr("x");

                this.oy = this.attr("y");

                this.animate({ "fill-opacity": .2 }, 500);

            };

 //拖动事件

            var move = function (dx, dy) {

                var att = { x: this.ox + dx, y: this.oy + dy };

                this.attr(att);

                $("#test" + this.id).offset({ top: this.oy + dy + 10, left: this.ox + dx + 10 });

                for (var i = connections.length; i--; ) {

                    r.drawArr(connections[i]);

                }

            };

            //拖动结束后的事件

            var up = function () {

                this.animate({ "fill-opacity": 0 }, 500);

            };

            //创建绘图对象

            var r = Raphael("holder", $(window).width(), $(window).height());

            //绘制节点

            var shapes = [

                        r.rect(190, 100, 60, 40, 4),

                        r.rect(290, 80, 60, 40, 4),

                        r.rect(290, 180, 60, 40, 4),

                        r.rect(450, 100, 60, 40, 4)

                     ];

            //定位节点上的文字

            $("#test1").offset({ top: 100 + 10, left: 190 + 10 });

            $("#test2").offset({ top: 80 + 10, left: 290 + 10 });

            $("#test3").offset({ top: 180 + 10, left: 290 + 10 });

            $("#test4").offset({ top: 100 + 10, left: 450 + 10 });

            //为节点添加样式和事件,并且绘制节点之间的箭头

            for (var i = 0, ii = shapes.length; i < ii; i++) {

                var color = Raphael.getColor();

                shapes[i].attr({ fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2, cursor: "move" });

                shapes[i].id = i + 1;

                shapes[i].drag(move, dragger, up);

shapes[i].click(click);

shapes[i].dblclick(function () { alert(this.id) })

}

 //存储节点间的顺序

   connections.push(r.drawArr({ obj1: shapes[0], obj2: shapes[1] }));

   connections.push(r.drawArr({ obj1: shapes[1], obj2: shapes[2] }));

   connections.push(r.drawArr({ obj1: shapes[2], obj2: shapes[3] }));     

})

var startNode=null;//两个节点连线时,存储开始的节点

var saveNode=new Array();//存储两个节点

var tempArrPath=[];//两个点连线时用于暂时存储起始节点到鼠标的线段

function click(){

svaeNode.push(this);

if(saveNode.length==1){

startNode=this;

}

if(saveNode.length==2){

if(tempArrPath[0]!=undefined){

tempArrPath[0].arrPath.remove();

saveNode.splice(0,2);

objCrr={obj1:startNode,obj2:this};

connections.push(r.drawArr(objCrr));

}else{

startNode=this;
saveNode.splice(0,2);
saveNode.push(this);

}

}

}

在拖动事件中,动态改变了节点文本元素的位置

并且重绘了节点和箭头

drawArr是一个自定义方法,负责修改箭头的方向,代码如下

//随着节点位置的改变动态改变箭头

        Raphael.fn.drawArr = function (obj) {

if(obj.ibj2==null){

           var point = getStartEnd(obj.obj1, obj.obj2);

            var path1 = getArr(point.start.x, point.start.y, mouseX, mouseY-10, 8);

            for(var i=0;i<tempArrPath.Length;i++){

                tempArrPath[i].arrPath.remove();

            }

   tempArrPath=[];

  obj.arrPath=this.path(path2);

obj.arrPath.attr({"stroke-width":2});

tempArrPath.push(obj);

return;

}else{

            tempArrPath.splice(0,tempArrPath.Length);

            var point = getStartEnd(obj.obj1, obj.obj2);

            var path1 = getArr(point.start.x, point.start.y, point.end.x, point.end.y, 8);

            if (obj.arrPath) {

                obj.arrPath.attr({ path: path1 });

            } else {

                obj.arrPath = this.path(path1);

            }

            return obj;

}

        

};

首先需要确定箭头的起始位置,

point包含两个点,

point.start为起点,

point.end为终点,

然后需要确定箭头的绘图路径

一个箭头包含三个线段,四个点

1:起点,2:终点,3:箭头终点1,4:箭头终点2





在此函数中,判断如果箭头已经被绘制过,

只要修改属性即可

如果没有被绘制过,则需要重新绘制

 

下面来看一下动态确定起点和终点的代码

function getStartEnd(obj1, obj2) {
var bb1 = obj1?bj1.getBBox():null;
bb2 = obj2?j2.getBBox():null;
var p = [

bb1?{ x: bb1.x + bb1.width / 2, y: bb1.y - 1 }:{},
bb1?{ x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1 }:{},

bb1?{ x: bb1.x - 1, y: bb1.y + bb1.height / 2 }:{},
bb1?{ x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2 }:{},
bb2?{ x: bb2.x + bb2.width / 2, y: bb2.y - 1 }:{},
bb2?{ x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1 }:{},
bb2?{ x: bb2.x - 1, y: bb2.y + bb2.height / 2 }:{},
bb2?{ x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2 }:{},

];
var d = {}, dis = [];
for (var i = 0; i < 4; i++) {
for (var j = 4; j < 8; j++) {
var dx = Math.abs(p[i].x - p[j].x),
dy = Math.abs(p[i].y - p[j].y);
if (
(i == j - 4) ||
(((i != 3 && j != 6) || p[i].x < p[j].x) &&
((i != 2 && j != 7) || p[i].x > p[j].x) &&
((i != 0 && j != 5) || p[i].y > p[j].y) &&
((i != 1 && j != 4) || p[i].y < p[j].y))
) {
dis.push(dx + dy);
d[dis[dis.length - 1]] = [i, j];
}
}
}
if (dis.length == 0) {
var res = [0, 4];
} else {
res = d[Math.min.apply(Math, dis)];
}
var result = {};
result.start = {};
result.end = {};
result.start.x = p[res[0]].x;
result.start.y = p[res[0]].y;
result.end.x = p[res[1]].x;
result.end.y = p[res[1]].y;
return result;
}

//添加线条的方法 
function addLine(){

if(startNode==null){

alert("还没有选择节点");
return -1;

}else{

objCrr={obj1:startNode,obj2:null};

}

}
//获取组成箭头的三条线段的路径

        function getArr(x1, y1, x2, y2, size) {

            var angle = Raphael.angle(x1, y1, x2, y2);//得到两点之间的角度

            var a45 = Raphael.rad(angle - 45);//角度转换成弧度

            var a45m = Raphael.rad(angle + 45);

            var x2a = x2 + Math.cos(a45) * size;

            var y2a = y2 + Math.sin(a45) * size;

            var x2b = x2 + Math.cos(a45m) * size;

            var y2b = y2 + Math.sin(a45m) * size;

            var result = ["M", x1, y1, "L", x2, y2, "L", x2a, y2a, "M", x2, y2, "L", x2b, y2b];

            return result;

        }

 

页面

<input type="button" onclick="addLine()" value="添加线条"/>

<div id="holder"></div>

<div id="test1" class="test">测试1</div>

<div id="test2" class="test">测试2</div>

<div id="test3" class="test">测试3</div>

<div id="test4" class="test">测试4</div>


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript svg Raphael