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 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>
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>
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- 只需四个步骤几行代码,即可快速实现直播弹幕功能
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- JavaScript 基础、进阶以及 Ubuntu 系统中的 JavaScript 开发调试工具
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 设计模式---状态模式在web前端中的应用
- SUI踩坑记录
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法