这回是真正的考验了,要实现设备的鼠标拖曳功能。
这个功能理论上比较简单,但是为了兼容性,几乎吐血。
实现的方法有很多,这里仅列举一种。
核心就在于坐标变换,主要有三点注意
针对ie的embed,需要注意设置wmode="Transparent"属性,这样可以不影响页面的鼠标事件。
再有就是IE/asv不支持offsetX方法,所以需要自行设法计算鼠标点击位置相对设备的坐标。
Ie和opera对clientx的取值不同ie是相对svg元素的坐标,opera是相对整个页面的坐标,因此移动函数采用了不同的算法。
6dev.htm
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- <title>
- 设备
- </title>
- <meta http-equiv="X-UA-Compatible" content="chrome=1">
- <!-- legengd.html
- 1.显示设备(文字、图片)
- 2.拖动
- -->
- </head>
- <script type="text/javascript" language="javascript" src="./js/moveObjs.js"></script>
- <script type="text/javascript" language="javascript" src="./js/svgutil.js"></script>
- <script type="text/javascript" language="javascript" src="./js/topo.js"></script>
-
- <script>
-
- </script>
-
- <body bgcolor="#ffffff">
-
-
- <br>
- <button onclick="show()">开始</button><br>
- <button onclick="zoomby(0.5)">缩小2倍cor</button>
- <button onclick="zoomby(2)">放大 2倍cor</button>
- <button onclick="zoom(1,300,300)">还原</button><br>
- <button onclick="showsrc()">源码</button><br>
- <button onclick="movetest()">移动</button><br>
- <div id="divsvg" style="position: absolute;top:180;left:0"></div>
- <div id="pos"></div>
- <div id="pos1"></div>
- </body>
- <script>
-
-
- var svg;
- var svgw=400;
- var svgh=300;
- //var svgdoc;
- var plat;
-
- function show(){
-
- svg=initSVG(svgw,svgh);
- //延迟一下,最小是10ms
- var tidst=window.setTimeout(show1,20);
- }
-
- function show1(){
- //var svg;
- //svg=initSVG(200,200);
- //var svgdoc;
- svgdoc=getSVGDocument(svg);
- plat=getrootg(svg,svgdoc);
-
-
- //生成一个设备
- curentStyle="stroke:black;fill:green";
- var device=createDev("DEV00005",100,100,29.0,17.0,"./image/DEV_IP_R.gif","XM-BB-GSR12816-D-1.MAN(61.154.237.12)");
- }
-
- function movetest(){
- //验证一下svg的group能否整体移动
- var svgdoc=getSVGDocument(svg);
- var plat=svgdoc.getElementById('DEV00005');
-
- plat.setAttribute("transform","translate(0,50)");
-
- }
-
- </script>
- </html>
相关的操作进行了一下封装
设备相关的。topo.js
- //3.二级函数
- //这里的位置和大小是由摆放算法确定的
-
- //节点。别名,叫设备有点太具体
- function createNode(id,x,y,width,height,imageSrc,name,target,style){
- var node=createDev(id,x,y,width,height,imageSrc,name,target,style);
- return node;
- }
-
- function createDev(id,left,top,width,height,imageSrc,name,target,style){
-
- //设备首先包含一个group
- style="fill:red";
- var group=createGroup(id,left,top,width,height ,name,style);
- //group.setAttribute("hasAlarm",false);
- //if (target == undefined){
- if (!target){
- var svgdoc1=getSVGDocument(svg);
- var plat1=getrootg(svg,svgdoc1);
- plat1.appendChild(group);
- }
- else{
- target.appendChild(group);
- }
-
-
- //在svg中,元素位置都是相对svg的。文本显示在起点的右上,矩形和图片显示在右下
- //设备的图片
- var image=createImage(top,left,width,height,imageSrc);
-
- group.appendChild(image);
-
- //设备的名称
- style="fill:blue;cursor:move";
- var namebox=createText(top,left,name,style);
- group.appendChild(namebox);
-
- //相对坐标移动
- //移动的相关事件
- if(isIE){
-
- group.setAttribute("onmousedown","dragie(evt,this)");
- }
- else{
- group.setAttribute("onmousedown","drago(evt,this)");
- }
-
-
- //可选,用于绝对坐标移动
- group.movetopos=function(ckx,cky){
-
- group.setAttribute("x",ckx);
- group.setAttribute("y",cky);
- image.setAttribute("x",ckx);
- image.setAttribute("y",cky);
- namebox.setAttribute("x",ckx);
- namebox.setAttribute("y",cky);
- }
- return group;
- }
-
- //创建电路
- //连线的位置需要根据设备的起点和大小进行计算,top对应y,left对应x.top+weight/2
-
- function createCircuit(id,x1,y1,x2,y2,name,title,id1,id2,target,style){
- var line=createLink(id,x1,y1,x2,y2,name,title,target,style);
- //起点
- var svgdoc1=getSVGDocument(svg);
-
- var fromObj=svgdoc1.getElementById(id1);
-
- //var fromLinks=fromObj.getAttribute("fromLinks");
- var fromLinks=fromObj.fromLinks;
- if(fromLinks==null){
- fromLinks=new Array();
-
- }
- //追加到数组末尾,便于拖动时计算
- //alert(fromLinks.length);
- fromLinks[fromLinks.length]=line;
- //fromObj.setAttribute("fromLinks",fromLinks);
- fromObj.fromLinks=fromLinks;
- //alert(fromLinks.length);
- //var fromLink=fromObj.fromLinks;;
- //alert(fromLink[0].id);
- //终点
- var toObj=svgdoc1.getElementById(id2);
- var tolinks=toObj.toLinks;
- if(tolinks==null){
- tolinks=new Array();
- toObj.setAttribute("toLinks",tolinks);
- }
- //追加到数组末尾,便于拖动时计算
- tolinks[tolinks.length]=line;
- toObj.toLinks=tolinks;
-
- //位置和大小。
- line.setAttribute("hasAlarm",false);
-
-
- return line;
- }
-
- //创建线型
- function createStroke(line){
- var curstyle=line.getAttribute("oristyle");
- var newstyle=";stroke-dasharray: 9, 5";
- var style=curstyle+newstyle;
- //alert(style);
- line.setAttribute("style",style);
- }
- //删除线型
- function removeStroke(line){
- var curstyle=line.getAttribute("oristyle");
- //alert(curstyle);
- line.setAttribute("style",curstyle);
- }
移动相关的movobjs.js
这个算法参照了网上的一个经典方法,非常简洁。
- var xx=0,yy=0;
- var moveobj=null,ckleft=0,cktop=0,ckw=0,ckhei=0,ckto="";
- var tempx,tempy;
- var showDevRelaCir=true;
- var fromLinks=null;
- var toLinks=null;
- var moving;
-
- function dealLineWhenChoose(moveobj){
- //处理设备相关的电路信息
-
- //点中设备的相关电路变虚线
- if(showDevRelaCir==true){
-
- //清除前次的线型
- if(fromLinks!=null)
- for(var i=0;i<fromLinks.length;i++){
- removeStroke(fromLinks[i]);
- }
- if(toLinks!=null)
- for(var i=0;i<toLinks.length;i++){
- removeStroke(toLinks[i]);
- }
- //重画线型
- fromLinks=moveobj.fromLinks;
- // alert(fromLinks.length);
- if(fromLinks!=null)
- for(var i=0;i<fromLinks.length;i++){
- createStroke(fromLinks[i]);
- }
- toLinks=moveobj.toLinks;
- if(toLinks!=null)
- for(var i=0;i<toLinks.length;i++){
- createStroke(toLinks[i]);
- }
- }
- }
-
- //js移动设备
- function movdev(moveobj,ckx,cky){
-
-
- if(moveobj!=null){
- moveobj.setAttribute("transform","translate("+ckx+","+cky+")");
-
- //移动相关连线
-
- // var x=parseInt(moveobj.getAttribute("x"))+parseInt(moveobj.width)/2;
- //var y=parseInt(moveobj.getAttribute("y"))+parseInt(moveobj.height)/2;
- var x=parseInt(moveobj.getAttribute("x"))+ckx+parseInt(moveobj.getAttribute("width"))/2;
-
- var y=parseInt(moveobj.getAttribute("y"))+cky+parseInt(moveobj.getAttribute("height"))/2;
- //alert(x+","+y);
- var fromLinks=moveobj.fromLinks;
- if(fromLinks!=null)
- for(var i=0;i<fromLinks.length;i++){
- fromLinks[i].setAttribute("x1",x);
- fromLinks[i].setAttribute("y1",y);
- //fromLinks[i].setAttribute("transform","translate("+ckx+","+cky+")");
- //dealLineWhenObjMove(fromLinks[i]);
- }
- var toLinks=moveobj.toLinks;
- if(toLinks!=null)
- for(var i=0;i<toLinks.length;i++){
- toLinks[i].setAttribute("x2",x);
- toLinks[i].setAttribute("y2",y);
- //toLinks[i].setAttribute("transform","translate("+ckx+","+cky+")");
- //dealLineWhenObjMove(toLinks[i]);
- }
- }
-
- }
-
- //方法1,使用translate方法进行相对移动.
- function drago(evt,obj){
-
- //获得事件的父对象(group)
- var oc=evt.target;
- var o=evt.target.parentNode;
- var d=document;
- //var d=document.getElementById('divsvg');
- //var d=getSVGDocument(svg);
- if(!evt)evt=window.event;
-
- //记录down点击的相对位置(注意,是相对svg/divsvg的位置)
- var x=evt.layerX?evt.layerX:evt.offsetX,y=evt.layerY?evt.layerY:evt.offsetY;
- //获得svg的初始位置,用于计算坐标
- var divsvg=document.getElementById('divsvg');
- var dtop=delPx(divsvg.style.top);
- var dleft=delPx(divsvg.style.left);
-
-
- //记录初始的位置信息
- var ttx=o.getAttribute("x");
- var tty=o.getAttribute("y");
-
-
-
- dealLineWhenChoose(o);
-
-
- if(o.setCapture)
- o.setCapture();
- else if(window.captureEvents)
- window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
-
- //opera的svg不会遮挡document的事件,但是ie会
- d.onmousemove=function(a){
- if(!a)a=window.event;
- if(!a.pageX)a.pageX=a.clientX;
- if(!a.pageY)a.pageY=a.clientY;
-
- //目标的相对位置(注意,要考虑svg的初始位置影响)
- var tx=a.pageX-x-dleft-ttx,ty=a.pageY-y-dtop-tty;
-
-
-
- //这个每次都是从最初位置开始移动。
- movdev(o,tx,ty);
- };
-
- d.onmouseup=function(){
- if(o.releaseCapture){
-
- o.releaseCapture();
- }
- else if(window.captureEvents)
- window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
- d.onmousemove=null;
- d.onmouseup=null;
- };
-
- }
-
-
- //方法1,使用translate方法进行相对移动.
- function dragie(evt,obj){
-
- //获得事件的父对象(group)
- var oc=evt.target;
- var o=evt.target.parentNode;
- var d=document;
- if(!evt)evt=window.event;
-
-
- //获得svg的初始位置,用于计算坐标
- var divsvg=document.getElementById('divsvg');
- var dtop=delPx(divsvg.style.top);
- var dleft=delPx(divsvg.style.left);
-
-
- //记录初始的位置信息(不用)
- var ttx=o.getAttribute("x");
- var tty=o.getAttribute("y");
-
- xx=evt.clientX;
- yy=evt.clientY;
-
- var tran;
- var trans=o.getAttribute("transform");
- if(trans){
- tran=trans.substring(10,trans.length-1);
- var tranpara=tran.split(",");
- ckleft=parseInt(tranpara[0]);
- cktop=parseInt(tranpara[1]);
- }
-
-
-
-
- if(o.setCapture)
- o.setCapture();
- else if(window.captureEvents)
- window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
-
- dealLineWhenChoose(o);
-
- //opera的svg不会遮挡document的事件,ie需要设置成透明
- d.onmousemove=function(a){
- if(!a)a=window.event;
- if(!a.pageX)a.pageX=a.clientX;
- if(!a.pageY)a.pageY=a.clientY;
-
- //目标的相对位置(注意,要考虑svg的初始位置影响)
- //由于ie不能取到初始的offset,所以算法和opera不同,但是效果相同
- //var tx=a.pageX-x-dleft-ttx,ty=a.pageY-y-dtop-tty;
- var tx=a.pageX+ckleft-xx-dleft,ty=a.pageY+cktop-yy-dtop;
-
-
-
- //这个每次都是从最初位置开始移动。
- movdev(o,tx,ty);
- };
-
- d.onmouseup=function(){
- if(o.releaseCapture){
-
- o.releaseCapture();
- }
- else if(window.captureEvents)
- window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
- d.onmousemove=null;
- d.onmouseup=null;
- };
-
- }
-
-
-
-
- function delPx(pos){
- return (parseInt(pos.substring(0,pos.length-2)));
- }