基于JAVA WEB的AHP层次分析法实践--JS的界面组件

使用D3.js为基础。写一个能够响应拖动、圈选、添加删除节点和连线的组件类。为用户设计模型提供图形操作界面。

function flowchart()
{
var testTxt=null;
var lineCanvas=null;
var nodeCanvas=null;
var allNode=[];
var nodeCount=0;
var allLink=[];
var linkCount=0;

//整体拖动的临时变量
var selectedNodes=function(){};
selectedNodes.nodeList=[];
selectedNodes.xlist=[];
selectedNodes.ylist=[];
selectedNodes.x=0;
selectedNodes.y=0;

//选定的连线
var selectedLink=null;

//圈选的行为
var isRangSelect=false;
var selectRang=new Object;

//插入节点的初始化选项
var isInsertNodeStatus=true;
var insertNodeType="top";

//按下F2,准备连线的临时设置
var isAddLink=false;
var tempLink=null;

//设置节点拖动行为
var drag =d3.behavior.drag()
.on("dragstart", dragStart)
.on("drag", dragmove);

var that=this;

this.canvas=null;
this.svg=null;
this.caseData=null;

//初始化结构图对象
if(this.init==undefined || this.init==null || this.init=="undefined")
{
this.init=function(desktop)
{
that.canvas=document.getElementById(desktop);
that.svg=d3.select("#"+desktop).append("svg");
lineCanvas=that.svg.append("g");
nodeCanvas=that.svg.append("g");
tempLink=that.svg.append("g");
testTxt=that.svg.append("text").text("测试信息");

//画布鼠标点击行为响应
that.svg.on("mousedown",function(d){
//移除所有选择
if(event.target==this)
{
deSelectAll();

isRangSelect=true;
selectRang.rect=nodeCanvas.append("rect")
.attr("class","selectRang");

selectRang.x1=d3.event.x;
selectRang.y1=d3.event.y;

if(isAddLink)
{
tempLink.selectAll("rect").remove();
tempLink.selectAll("line").remove();
isAddLink=false;
}
}

//如果是插入状态,则插入节点
if(isInsertNodeStatus)
{
var xOffset=that.canvas.getBoundingClientRect().left;
var yOffset=that.canvas.getBoundingClientRect().top;
var x=d3.event.x-xOffset;
var y=d3.event.y-yOffset;
var nodeData={"id":0,"type":insertNodeType,"x":x,"y":y,"name":"未命名节点","next":{},"previous":{},"matrix":[{}]};
that.addNode(nodeData);
isInsertNodeStatus=false;
}
})
.on("mousemove",drawSelectRect)
.on("mouseup",endDrawSelectRect)
.on("keydown",desktopKeydown);
}
}

//初始化新的文件
if(this.newFile==undefined || this.newFile==null || this.newFile=="undefined")
{
this.newFile=function()
{
var len=allNode.length;
for(var i=0;i<len;i++)
{
allNode[i].remove();
}
len=allLink.length;
for(var i=0;i<len;i++)
{
allLink[i].remove();
}

selectedLink=null;

selectedNodes.nodeList=[];
selectedNodes.xlist=[];
selectedNodes.ylist=[];
selectedNodes.x=0;
selectedNodes.y=0;
}
}

//删除选定内容
if(this.deleteSelected==undefined || this.deleteSelected==null || this.deleteSelected=="undefined")
{
this.deleteSelected=function()
{
var len=selectedNodes.nodeList.length;
for(var i=0;i<len;i++)
{
deleteNode(selectedNodes.nodeList[i]);
}
selectedNodes.nodeList=[];

if(selectedLink!=null)
{
deleteLink(selectedLink);
selectedLink=null;
}

//更新连线
keepLink();
}
}

//添加节点
if(this.addNewNode==undefined || this.addNewNode==null || this.addNewNode=="undefined")
{
this.addNode=function(info)
{
//添加对象,并支持拖动
var node=nodeCanvas.append("g")
.attr("transform", "translate("+ info.x +"," + info.y + ")")
.attr("cursor","pointer")
.call(drag);

//添加背景
var backGround=node.append("rect")
.attr("width",80)
.attr("height",30)
.attr("x",-40)
.attr("y",-15)
.attr("rx",5)
.attr("ry",5);

switch(info.type)
{
case "top":
backGround.attr("class","topnode")
break;
case "center":
backGround.attr("class","centernode")
break;
case "bottom":
backGround.attr("class","bottomnode")
break;
}

//添加标签
var txt=node.append("text")
.attr("class","nodeText")
.attr("transform", "translate(0,5)")
.text(info.name);

node.attr("id",info.id)
.attr("x",info.x)
.attr("y",info.y);

node.info=info;

allNode[nodeCount]=node;
nodeCount++;

return node;
}
}

//删除节点
function deleteNode(node)
{
var i=0;
while(i<allLink.length)
{
var line=allLink[i];
if(line.soure.attr("id")==node.attr("id") || line.target.attr("id")==node.attr("id"))
{
deleteLink(line);
}
else
{
i++;
}
}
node.remove();
}

//添加连线
if(this.addLink==undefined || this.addLink==null || this.addLink=="undefined")
{
this.addLink=function(x1,y1,x2,y2)
{
var linkCount=allLink.length;
var index=0;
for(var i=0;i<linkCount;i++)
{
index=d3.max([index,Math.round(allLink[i].attr("id"))]);
}
index++;
var line=lineCanvas.append("line")
.attr("x1",x1.toString())
.attr("y1",y1.toString())
.attr("x2",x2.toString())
.attr("y2",y2.toString())
.attr("class","link")
.attr("cursor","pointer")
.attr("id",index)
.on("click",selectLink);
return line;
}
}

//删除连线
function deleteLink(line)
{
//从连线数组中删除连线
var linkCount=allLink.length;
for(var i=0;i<linkCount;i++)
{
if(allLink[i].attr("id")==line.attr("id"))
{
//删除所有相关的上下文信息
var firstNode=allLink[i].soure;
var lastNode=allLink[i].target;

//从前项删除后项
var str=firstNode.info.next;
var arr=str.split(",");
arr.splice(arr.indexOf(lastNode.id),1);
firstNode.info.next=arr.join(",");

//从后项删除前项
str=lastNode.info.previous;
arr=str.split(",");
arr.splice(arr.indexOf(firstNode.id),1);
lastNode.info.previous=arr.join(",");

//删除连线对象
line.remove();
allLink.splice(i,1);
break;
}
}
}

//准备连线数据
if(this.readyToLink==undefined || this.readyToLink==null || this.readyToLink=="undefined")
{
this.readyToLink=function()
{
var len=selectedNodes.nodeList.length;
if(len<=0) return;

tempLink.selectAll("rect").remove();
tempLink.selectAll("line").remove();
tempLink.append("rect")
.attr("width",20)
.attr("height",20)
.attr("x",-10)
.attr("y",-10)
.attr("class","linknode");

for(var i=0;i<len;i++)
{
tempLink.append("line")
.attr("x1",selectedNodes.nodeList[i].attr("x"))
.attr("y1",selectedNodes.nodeList[i].attr("y"))
.attr("x2",0)
.attr("y2",0)
.attr("class","link")
.style("pointer-events","none");
}
isAddLink=true;
}
}

//设置数据
if(this.data==undefined || this.data==null || this.data=="undefined")
{
this.data=function(data)
{
that.caseData=data;

allNode=[];

var data=that.caseData;
var node=null;

//决策节点
var nodes=getArrayFromJsonNode(data.top.node);
var topCount=nodes.length;
for(i=0;i<topCount;i++)
{
node=that.addNode(nodes[i]);
}

//中间节点
nodes=getArrayFromJsonNode(data.center.node);
var topCount=nodes.length;
for(i=0;i<topCount;i++)
{
node=that.addNode(nodes[i]);
}

//方案节点
nodes=getArrayFromJsonNode(data.bottom.node);
var topCount=nodes.length;
for(i=0;i<topCount;i++)
{
node=that.addNode(nodes[i]);
}
}
}

//根据数据重新作图
if(this.draw==undefined || this.draw==null || this.draw=="undefined")
{
this.draw=function()
{
//删除旧的连线
var linkCount=allLink.length;
for(i=0;i<linkCount;i++)
{
allLink[i].remove();
}

allLink=[];
linkCount=0;

//重新连线
var nodeCount=allNode.length;
for(i=0;i<nodeCount;i++)
{
var soureNode=allNode[i];


var type=(typeof soureNode.info.next);
if(type=="string")
{
var nextStr=soureNode.info.next;
var nexts=nextStr.split(",");
var len=nexts.length;
for(j=0;j<len;j++)
{
var objNode=getNodeByID(nexts[j]);
if(objNode!=null)
{
var top=Math.round(soureNode.info.y)+15;
var bottom=Math.round(objNode.info.y)-15;
var line=that.addLink(soureNode.info.x,top,objNode.info.x,bottom);
line.soure=soureNode;
line.target=objNode;
allLink[linkCount]=line;
linkCount++;
}
}
}
}
}
}

//返回指定ID的节点
function getNodeByID(id)
{
var len=allNode.length;
for(var i=0;i<len;i++)
{
if(allNode[i].info.id==id)
{
return allNode[i];
}
}
return null;
}

//返回JSON的数组形式
function getArrayFromJsonNode(node)
{
var arr=[];
if(node!="undefined" && node!=undefined && node!=null)
{
var len=node.length;
if(len!="undefined" && len!=undefined && len!=null)
{
for(i=0;i<len;i++)
{
arr[i]=node[i];
}
}
else
{
arr[0]=node;
}
}
return arr;
}

//是否已经被选择
function isSelected(node)
{
var len=selectedNodes.nodeList.length;
for(var i=0;i<len;i++)
{
if(selectedNodes.nodeList[i].attr("id")==node.attr("id"))
{
return true;
}
}
return false;
}

//取消所有选择
function deSelectAll()
{
var len=selectedNodes.nodeList.length;
for(var i=0;i<len;i++)
{
selectedNodes.nodeList[i].selectAll("rect").style("stroke-width","1");
}
selectedNodes.nodeList=[];

if(selectedLink!=null)
{
selectedLink.style("stroke-width","1").style("stroke","#CCC");
selectedLink=null;
}
}

//开始拖动节点
function dragStart()
{
var currentNode= getNodeByID(d3.select(this).attr("id"));

if(isAddLink)
{
if(currentNode.info.type=="bottom")
{
alert("不能连接到方案节点。");
return;
}

linkCount=allLink.length;

var len=selectedNodes.nodeList.length;
for(i=0;i<len;i++)
{
var soureNode=selectedNodes.nodeList[i];
if(soureNode!=null)
{
var next=currentNode.info.next;
var nextArr=next.split(",");
if(nextArr.indexOf(soureNode.attr("id"))<0)
{
var top=Math.round(currentNode.info.y)+15;
var bottom=Math.round(soureNode.info.y)-15;
var line=that.addLink(currentNode.info.x,top,soureNode.info.x,bottom);
line.soure=soureNode;
line.target=currentNode;
allLink[linkCount]=line;
linkCount++;
}
}
}

tempLink.selectAll("rect").remove();
tempLink.selectAll("line").remove();
isAddLink=false;
return;
}

if(!isSelected(currentNode))
{
if(!event.shiftKey)
{
deSelectAll();
}
selectedNodes.nodeList[selectedNodes.nodeList.length]=currentNode;
currentNode.selectAll("rect").style("stroke-width","5");
}
else
{
if(event.shiftKey)
{
var index=0;
while(index<selectedNodes.nodeList.length)
{
if(selectedNodes.nodeList[index].attr("id")==currentNode.attr("id"))
{
selectedNodes.nodeList[index].selectAll("rect").style("stroke-width","1");
selectedNodes.nodeList.splice(index,1);
}
else
{
index++;
}
}

return;
}
}

selectedNodes.x=currentNode.attr("x");
selectedNodes.y=currentNode.attr("y");

selectedNodes.xlist=[];
selectedNodes.ylist=[];

var len=selectedNodes.nodeList.length;
for(var i=0;i<len;i++)
{
selectedNodes.xlist[i]=selectedNodes.nodeList[i].attr("x");
selectedNodes.ylist[i]=selectedNodes.nodeList[i].attr("y");
}
}

//拖动节点对象响应函数
function dragmove(d) 
{
var currentNode=d3.select(this);
if(!isSelected(currentNode)) return;

var offsetX=selectedNodes.x-d3.event.x;
var offsetY=selectedNodes.y-d3.event.y;

var len=selectedNodes.nodeList.length;

for(var i=0;i<len;i++)
{
var objNode=selectedNodes.nodeList[i];

objNode.attr("x",selectedNodes.xlist[i]-offsetX);
objNode.attr("y",selectedNodes.ylist[i]-offsetY);
objNode.attr("transform", "translate("+objNode.attr("x")+"," + objNode.attr("y") + ")");
}
keepLink();
}

//保持连线
function keepLink()
{
linkCount=allLink.length;
for(var i=0;i<linkCount;i++)
{
var line=allLink[i];
var top=Math.round(line.soure.attr("y"))+15;
var bottom=Math.round(line.target.attr("y"))-15;
line.attr("x1",line.soure.attr("x"))
.attr("y1",top.toString())
.attr("x2",line.target.attr("x"))
.attr("y2",bottom.toString());
}
}

//描绘圈选范围
function drawSelectRect(d)
{
var xOffset=that.canvas.getBoundingClientRect().left;
var yOffset=that.canvas.getBoundingClientRect().top;

if(isAddLink)
{
testTxt.text(d3.event.x-xOffset);
tempLink.selectAll("rect")
.attr("transform", "translate("+(d3.event.x-xOffset)+"," + (d3.event.y-yOffset) + ")");

tempLink.selectAll("line")
.attr("x2",d3.event.x-xOffset)
.attr("y2",d3.event.y-yOffset);
}

if(isRangSelect)
{
selectRang.x2=d3.event.x;
selectRang.y2=d3.event.y;

var x1=d3.min([selectRang.x1,selectRang.x2])-xOffset;
var x2=d3.max([selectRang.x1,selectRang.x2])-xOffset;
var y1=d3.min([selectRang.y1,selectRang.y2])-yOffset;
var y2=d3.max([selectRang.y1,selectRang.y2])-yOffset;

selectRang.rect
.attr("x",x1.toString())
.attr("y",y1.toString())
.attr("width",x2-x1)
.attr("height",y2-y1);
}
}

//圈选结束
function endDrawSelectRect(d)
{
if(!isRangSelect) return;

var x1=Math.round(selectRang.rect.attr("x"));
var x2=Math.round(selectRang.rect.attr("x"))+Math.round(selectRang.rect.attr("width"));
var y1=Math.round(selectRang.rect.attr("y"));
var y2=Math.round(selectRang.rect.attr("y"))+Math.round(selectRang.rect.attr("height"));


deSelectAll();

var len=allNode.length;
for(var i=0;i<len;i++)
{
if(allNode[i].attr("x")>=x1 && allNode[i].attr("x")<=x2)
{
if(allNode[i].attr("y")>=y1 && allNode[i].attr("y")<=y2)
{
allNode[i].selectAll("rect").style("stroke-width","5");
selectedNodes.nodeList[selectedNodes.nodeList.length]=allNode[i];
}
}
}

selectRang.rect.remove();
isRangSelect=false;
}

//选择连线
function selectLink(d)
{
deSelectAll();

if(d3.select(this).style("stroke-width")==2)
{
d3.select(this).style("stroke-width","1").style("stroke","#CCC");
}
else
{
d3.select(this).style("stroke-width","2").style("stroke","#F00");
selectedLink=d3.select(this);
}
}

//画布上按键按下
function desktopKeydown(e)
{
switch(event.keyCode)
{
case 46:
that.deleteSelected();
break;
case 110:
that.deleteSelected();
break;
case 113:
that.readyToLink();
break;
case 27:
if(isAddLink)
{
tempLink.selectAll("rect").remove();
tempLink.selectAll("line").remove();
isAddLink=false;
}
break;
default:
break;
}
}

//代码结束
}

猜你喜欢

转载自blog.csdn.net/qq_42213965/article/details/80487971
今日推荐