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

基于html5 拖拽连线加强版实现

2014-12-02 12:10 411 查看
    自动折线,自动判断起始点坐标,拖拽位置变换,大小拖拽,箭头指向等功能,这个版本稍微复杂一点,

还有个简单版本的实现http://zha-zi.iteye.com/blog/1586814 这个应该比较容易理解坐标换算不太多

<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script type="text/javascript" src="ext/bootstrap.js"></script>
<!-- ENDLIBS -->
<script type="text/javascript" src="ext/ext-all-debug.js"></script>
<script src="js/kinetic-v3.10.2.min.js"></script>
<script>

Ext.onReady(function(){
/**
自动折叠连线算法
*/

var stage=new Kinetic.Stage({
container:'container',
width:1000,
height:1000
});
/**
箭头角度
*/
var arrowAngle=30;
/**
箭头半径
*/

var arrowRadius=5;
/**
箭头长度
*/
var arrowLenght=10;
/**
表示方向
*/
var E="E";
var W="W";
var S="S";
var N="N";
var layer=new Kinetic.Layer();
var flag=false;
var imgArray=[];
var lineArray=[];
var tmpMoveImg=null;
var loop=0;
function  Pos(x,y){
this.x=x;
this.y=y;
};
/**
img 图像
lineArrow 带有箭头的line
flag 图像与箭头的指向关系
*/
function LineImage(img,lineArrow,flag){
this.img=img;
this.lineArrow=lineArrow;
this.flag=flag
};

function LineArrow(line,arrow){
this.line=line;
this.arrow=arrow;
};
function NewImage(img,opsArray,group){
this.img=img;
this.group=group;
this.opsArray=opsArray;
};

var imgA= new Image();
var imgObjA;
var groupA;
imgA.onload=function(){
imgObjA= createImage(imgA,100,100,100,100)
var array=new Array();

groupA=new Kinetic.Group({
draggable:true
});
groupA.add(imgObjA);
layer.add(groupA);
addAnchor(groupA, 100, 100, "topLeft");
addAnchor(groupA, 200, 100, "topRight");
addAnchor(groupA, 200, 200, "bottomRight");
addAnchor(groupA, 100, 200, "bottomLeft");
var na=new  NewImage(imgObjA,array,groupA);
imgArray.push(na);
stage.add(layer);
}

var imgB= new Image();
var imgObjB;
var groupB;
imgB.onload=function(){
imgObjB= createImage(imgB,400,400,100,100)
var array=new Array();

groupB=new Kinetic.Group({
draggable:true
});
groupB.add(imgObjB);
layer.add(groupB);
addAnchor(groupB, 400, 400, "topLeft");
addAnchor(groupB, 500, 400, "topRight");
addAnchor(groupB, 500, 500, "bottomRight");
addAnchor(groupB, 400, 500, "bottomLeft");
var nb=new  NewImage(imgObjB,array,groupB);
imgArray.push(nb);

stage.add(layer);
}

var imgC= new Image();
var imgObjC;
var groupC;
imgC.onload=function(){
imgObjC= createImage(imgC,700,100,100,100)
var array=new Array();

groupC=new Kinetic.Group({
draggable:true
});
groupC.add(imgObjC);
layer.add(groupC);
addAnchor(groupC, 700, 100, "topLeft");
addAnchor(groupC, 800, 100, "topRight");
addAnchor(groupC, 800, 200, "bottomRight");
addAnchor(groupC, 700, 200, "bottomLeft");
var nc=new  NewImage(imgObjC,array,groupC);
imgArray.push(nc);

stage.add(layer);
}

var rect=new Kinetic.Rect({
x:0,
y:0,
width:1000,
height:1000,
fill:'white',
storke:'red',
storkeWidth:5

});
layer.add(rect);
imgA.src='img/db.png';
imgB.src='img/mj.png';
imgC.src="img/kt1.png";

rect.on('dblclick',function(){

if(loop%2==0){
flag=true;
for(var i=0;i<imgArray.length;i++){
imgArray[i].group.setDraggable(false);

}
}else{
flag=false;

for(var i=0;i<imgArray.length;i++){

imgArray[i].group.setDraggable(true);
imgArray[i].img.on('mouseover',function(){

var p=new Pos(this.getAbsolutePosition().x,this.getAbsolutePosition().y);
tmpMoveImg=getImgByPos(p);

});

imgArray[i].group.on('dragmove',function(){

for(var j=0;j<tmpMoveImg.opsArray.length;j++){
var realPoints=[];

if(tmpMoveImg.opsArray[j].flag){
calculateStartEndPos(tmpMoveImg.opsArray[j].img,this.children[0],realPoints);
}else{
calculateStartEndPos(this.children[0],tmpMoveImg.opsArray[j].img,realPoints);
}
tmpMoveImg.opsArray[j].lineArrow.line.setPoints(realPoints);
var arrowPoint= calculateArrowPointsByPoints(realPoints);
tmpMoveImg.opsArray[j].lineArrow.arrow.setPoints(arrowPoint);
layer.draw();
realPoints=[];
}
layer.draw();
});
imgArray[i].group.on('dragmove',function(){
for(var j=0;j<lineArray.length;j++){
//lineArray[j].hide();
//moveLineToTarget(lineArray[j])
}
});

}
}
loop++;

for(var i=0;i<imgArray.length;i++){
var innerFlag=false;
var points=[];//标记性的点,为了获取img 使用
var realPoints=[];//真正计算后合理的划线点
imgArray[i].img.on('mousedown',function(){

if(flag){
var pos= stage.getMousePosition();
points=[];
points.push(this.getAbsolutePosition().x);
points.push(this.getAbsolutePosition().y);
innerFlag=true;
}
});
imgArray[i].img.on('mouseup',function(){
if(flag&&innerFlag){
var pos= stage.getMousePosition();
points.push(this.getAbsolutePosition().x);
points.push(this.getAbsolutePosition().y);
//起始点
var p=new Pos(points[0],points[1]);
//结束点
var op=new Pos(points[2],points[3]);
// 划线起始图像
var opImg=getImgByPos(p);
// 划线结束图像
var owImg=getImgByPos(op);

if(opImg!=owImg){
calculateStartEndPos(opImg.img,owImg.img,realPoints);
var lineArrow= createLine(realPoints);
var opLine=new LineImage(opImg.img,lineArrow,true);
var owLine=new LineImage(owImg.img,lineArrow,false);
owImg.opsArray.push(opLine);
opImg.opsArray.push(owLine);
flag=false;
innerFlag=false;
points=[];
realPoints=[];
lineArray.push(lineArrow);
layer.add(lineArrow.line);

layer.add(lineArrow.arrow);
layer.draw();
bandEventToLine(lineArrow.line);

}

}
});
}
})
/**
* 通过坐标获取Img对象
*/
function getImgByPos(pos){
for(var i=0;i<imgArray.length;i++){
if(imgArray[i].img.getAbsolutePosition().x==pos.x&&imgArray[i].img.getAbsolutePosition().y==pos.y){
return imgArray[i];
}
}
}
/**
* 替换对方中line
*/
function replaceOppoLine(imgObj,oldLine,newLine){
for(var i=0;i<imgObj.opsArray.length;i++){

if(imgObj.opsArray[i].line==oldLine){
imgObj.opsArray[i].line=newLine;
}
}
}

/**
* 计算划线的开始坐标
*/
function calculateStartEndPos(imgStart,imgEnd,realPoints){
var realSx=0;
var realSy=0;
var realEx=0;
var realEy=0;

var sx=imgStart.getAbsolutePosition().x;
var sy=imgStart.getAbsolutePosition().y;
var swidth=imgStart.getWidth();
var sheight=imgStart.getHeight();
var ex=imgEnd.getAbsolutePosition().x;
var ey=imgEnd.getAbsolutePosition().y;
var ewidth=imgEnd.getWidth();
var eheight=imgEnd.getHeight();
var array=calculateXY(sy,sheight,ey,eheight ,sx,swidth,ex,ewidth);
var crossArray=null;
if((array[0]!=array[2])&&(array[1]!=array[3])){
var crossArray= calculateCrossPoints(array,sy,sheight,ey,eheight ,sx,swidth,ex,ewidth);
}
realPoints.push(array[0]);
realPoints.push(array[1]);
if(crossArray!=null)
for(var i=0;i<crossArray.length;i++){
realPoints.push(crossArray[i]);
}
realPoints.push(array[2]);
realPoints.push(array[3]);

}
/**
计算连线开始和结束坐标的位置
*/
function calculateXY(sy,sheight,ey,eheight,sx,swidth,ex,ewidth ){

var array=[];
if(sy==ey){
if(sx>ex){
array.push(sx);
array.push(sy+(sheight/2));
array.push(ex+ewidth);
array.push(sy+(eheight/2));
}else{
array.push(sx+swidth);
array.push(sy+(sheight/2));
array.push(ex);
array.push(sy+(eheight/2));
}

}else{
if(sy>ey&&(sy-ey>sheight)){
if(sx>ex){
if(sx-ex<swidth/2){
array.push(sx);
array.push(sy+(sheight/2));
array.push(ex);
array.push(ey+eheight/2);
}else{
array.push(sx);
array.push(sy+(sheight/2));
array.push(ex+(ewidth/2));
array.push(ey+eheight);
}

}else if(sx==ex){

array.push(sx+(swidth/2));
array.push(sy);
array.push(ex+(ewidth/2));
array.push(ey+eheight);
}else{
if(ex-sx<ewidth/2){
array.push(sx);
array.push(sy+(sheight/2));
array.push(ex);
array.push(ey+eheight/2);
}else{
array.push(sx+swidth);
array.push(sy+(sheight/2));
array.push(ex+(ewidth/2));
array.push(ey+eheight);
}

}
}else if(sy<ey&&(ey-sy>eheight)){
if(sx>ex){
if(sx-ex<swidth/2){
array.push(sx);
array.push(sy+sheight/2);
array.push(ex);
array.push(ey+eheight/2);
}else{
array.push(sx+(swidth/2));
array.push(sy+sheight);
array.push(ex+ewidth);
array.push(ey+(eheight/2));
}

}else if(sx==ex){

array.push(sx+(swidth/2));
array.push(sy+sheight);
array.push(ex+(ewidth/2));
array.push(ey);
}else{
if(ex-sx<ewidth/2){
array.push(sx);
array.push(sy+sheight/2);
array.push(ex);
array.push(ey+eheight/2);
}else{
array.push(sx+(swidth/2));
array.push(sy+sheight);
array.push(ex);
array.push(ey+(eheight/2));
}

}
}else{
if((sy<ey&&(ey-sy<eheight))||sy>ey&&(sy-ey<sheight)){
array.push(sx+swidth/2);
array.push(sy);
array.push(ex+ewidth/2);
array.push(ey);
}
}

}
return  array;
}
/**
计算折叠点的位置
*/
function calculateCrossPoints(array,sy,sheight,ey,eheight ,sx,swidth,ex,ewidth){

var pointsArray=[];
var x=array[0];
var y=array[1];
var x1=array[2];
var y1=array[3];
var f=false;
if((x-x1)>0&&(y-y1)>0){
f=true;
}
if((x1-x)>0&&(y1-y)>0){
f=true;
}
/**
y轴的多个折叠点
*/
if((sy>ey&&sy-ey<=sheight)||(sy<ey&&ey-sy<=eheight)){
if(sy>ey&&sy-ey<=sheight){
pointsArray.push(x);
pointsArray.push(y1-sheight);
pointsArray.push(x1);
pointsArray.push(y1-sheight);

}else if(sy<ey&&ey-sy<=eheight){
pointsArray.push(x);
pointsArray.push(y-eheight);
pointsArray.push(x1);
pointsArray.push(y-eheight);
}

}else if((sx>ex&&sx-ex<=sheight/2)||(sx<ex&&ex-sx<=eheight/2)){
/**
x轴的多个折点
*/
//x= sx-swidth/2
//y=y+sheight/2

if(sx-ex<sheight/2){

pointsArray.push(sx-ewidth);
pointsArray.push(sy+sheight/2);
pointsArray.push(sx-ewidth);
pointsArray.push(ey+eheight/2);
}else if(ex-sx<eheight/2){

pointsArray.push(ex-swidth);
pointsArray.push(sy+sheight/2);
pointsArray.push(ex-swidth);
pointsArray.push(ey+eheight/2);
}

}else{
/**
单个折叠点
*/
if(f){
if(x<x1){
pointsArray.push(x);
}else{
pointsArray.push(x1);
}
if(y<y1){
pointsArray.push(y1);
}else{
pointsArray.push(y);
}
}else{
if(x<x1){
pointsArray.push(x1);
}else{
pointsArray.push(x);
}
if(y<y1){
pointsArray.push(y1);
}else{
pointsArray.push(y);
}
}
}

return pointsArray;
}
function createImage(img,x,y,width,height){
var imgObj=new Kinetic.Image({
x:x,
y:y,
width:width,
height:height,
//draggable:true,
image:img,
name:"image",
});
imgObj.on("mouseover", function(){
document.body.style.cursor = "pointer";
});
imgObj.on("mouseout", function(){
document.body.style.cursor = "default";
});
return imgObj

}

/**
根据points 节点数组划线
*/
function createLine(points){

var line=new Kinetic.Line({
points:points,
stroke:'green',
strokeWidth:2,
lineCap:'round',
lineJoin:'round'

});
var lenght=points.length;
var x=points[lenght-4];
var y=points[lenght-3];
var x1=points[lenght-2];
var y1=points[lenght-1];
var arrow=createArrow(calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1)),"black");

var la =new LineArrow(line,arrow);
return la;
}
function bandEventToLine(line){
line.saveData();

line.on("mouseover", function(){
document.body.style.cursor = "pointer";
});
line.on("mouseout", function(){
document.body.style.cursor = "default";
});
}
/**
通过line计算 arrow 的points 数组
*/
function calculateArrowPointsByLine(line){
var points=line.getPoints();
var lenght=points.length;
var x=points[lenght-4];
var y=points[lenght-3];
var x1=points[lenght-2];
var y1=points[lenght-1];
return calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1));

}
function calculateArrowPointsByPoints(points){
var lenght=points.length;
var x=points[lenght-4];
var y=points[lenght-3];
var x1=points[lenght-2];
var y1=points[lenght-1];
return calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1));
}
/**
计算箭头朝向
*/
function calculateArrowAspect(x,y,x1,y1){

if(x==x1){
if(y>y1){
return N;
}else{
return S;
}
}else if(y==y1){
if(x>x1){
return W;
}else{
return E;

}
}
}

/**
计算箭头具体位置
*/
function calculateArrowPosition(x,y,aspect){

var points=[];
switch(aspect){
case N:
points.push(x);
points.push(y);
points.push(x-arrowRadius);
points.push(y+arrowLenght);
points.push(x+arrowRadius);
points.push(y+arrowLenght);
break;
case S:
points.push(x);
points.push(y);
points.push(x-arrowRadius);
points.push(y-arrowLenght);
points.push(x+arrowRadius);
points.push(y-arrowLenght);

break;
case E:
points.push(x);
points.push(y);

points.push(x-arrowLenght);
points.push(y+arrowRadius);

points.push(x-arrowLenght);
points.push(y-arrowRadius);

break;
case W:
points.push(x);
points.push(y);
points.push(x+arrowLenght);
points.push(y+arrowRadius);

points.push(x+arrowLenght);
points.push(y-arrowRadius);

break;
}

return points;
}
function createArrow(points,fill){
var arrow=new Kinetic.Polygon({
points: points,
fill: fill,
stroke: "black",
strokeWidth: 1
});
return arrow;
}
function addAnchor(group,x,y,name){
var stage=group.getStage();
var layer=group.getLayer();
var anchor=new Kinetic.Circle({
x:x,
y:y,
stroke:'#666',
fill:'green',
radius:1,
name:name,
draggable:true
});
anchor.on('dragmove',function(){
update(group, this);
layer.draw();
});
anchor.on('dragend',function(){
group.setDraggable(true);
layer.draw();

});
anchor.on('mousedown touchstar',function(){
group.setDraggable(false);
//this.moveToTop();

});
anchor.on('mouseover',function(){
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setRadius(3);
layer.draw();

});
anchor.on('mouseout',function(){
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setRadius(1);
layer.draw();

});
group.add(anchor);
}
function update(group,activeAnchor){
var topLeft=group.get(".topLeft")[0];
var topRight=group.get(".topRight")[0];
var bottomLeft=group.get(".bottomLeft")[0];
var bottomRight=group.get(".bottomRight")[0];

var image=group.children[0];

switch(activeAnchor.getName()){
case "topLeft":
topRight.attrs.y = activeAnchor.attrs.y;
bottomLeft.attrs.x = activeAnchor.attrs.x;
break;
case "topRight":
topLeft.attrs.y = activeAnchor.attrs.y;
bottomRight.attrs.x = activeAnchor.attrs.x;
break;
case "bottomRight":
bottomLeft.attrs.y = activeAnchor.attrs.y;
topRight.attrs.x = activeAnchor.attrs.x;
break;
case "bottomLeft":
bottomRight.attrs.y = activeAnchor.attrs.y;
topLeft.attrs.x = activeAnchor.attrs.x;
break;
}

image.setPosition(topLeft.attrs.x, topLeft.attrs.y);
image.setSize(topRight.attrs.x - topLeft.attrs.x, bottomLeft.attrs.y - topLeft.attrs.y);
}

});

</script>
</head>
<body>
<div id="container"></div>
</body>
</html>



 



 

 



 





大小: 76.3 KB



大小: 167.2 KB

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