JavaScriptでcanvasを使わないでネットワーク図を書いてみるよ

ドラッグアンドドロップの動作後のアクションに、AjaxでサーバサイドとAPI通信させてDB連携などして位置情報を保管共有できれば、いいな。
結線や線の削除をする動作を入れたり、オブジェクトの作成・削除を入れたり。
各線に両端のポート名を入れたり。
監視システムと連動させて、ネットワーク異常時に線を赤くしたり。
線や、オブジェクトにカーソルを合わせたら、統計情報のAPIをつついてhichartのようなグラフを表示したり。
色々とやりたいことが膨らんでくる!

論理ネットワーク図(IPやVLANが分かる図)と、物理結線図(装置やポートが分かる図)の両方を切り替えてみたり。
物理的な支障箇所と、論理的な影響箇所が一目でわかる仕組みが欲しいな。

まだまだ先は長そうだけど、コツコツつくってみるかな。

サーバサイドは、Mojoliciousが拡張性があって、とっつきやすそうなのでフレームワークに使ってみるかな。

 

<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-
ui.min.js"></script>
<style>
.line{
    position: absolute;
    border-top: solid 1px #FF4981;
    -moz-transform-origin:0% 0%;
    -webkit-transform-origin:0% 0%;
    transform-origin:0% 0%;
    float: left;
}
.object {
    border: 4px solid black;
    width: 50px;
    height: 30px;
    position: absolute;
    cursor:pointer;
    z-index:200;
    text-align: center;
    vertical-align: middle;
    background: #ccc;
    font-size: 80%;
}
</style>

<script language="JavaScript">
var xCorrect = 25+4;
var yCorrect = 15+4;
var objects = {
"L2SW11":[800,150,["L2SW12","L2SW17","L2SW1B"]],
"L2SW12":[500,20,["L2SW11","L2SW13","L2SW14","L2SW15","L2SW16"]],
"L2SW13":[600,150,["L2SW12","L2SW18","L2SW1C"]],
"L2SW14":[450,150,["L2SW12","L2SW19","L2SW1A","L2SW1D"]],
"L2SW15":[300,150,["L2SW12"]],
"L2SW16":[200,150,["L2SW12"]],
"L2SW17":[900,250,["L2SW11"]],
"L2SW18":[600,250,["L2SW13"]],
"L2SW19":[300,250,["L2SW14"]],
"L2SW1A":[400,250,["L2SW14"]],
"L2SW1B":[800,250,["L2SW11"]],
"L2SW1C":[700,250,["L2SW13"]],
"L2SW1D":[500,250,["L2SW14"]]
};
function init() {
  for(var objName in objects){
    var objDiv = $("<div id='" + objName + "'>" + objName + "</div>")
              .addClass("object")
              .css({
                "left": objects[objName][0],
                "top": objects[objName][1],
              });
    $(document.body).append(objDiv);
    for(var i=0; i < objects[objName][2].length; ++i){
      var dstObjName = objects[objName][2][i];
      var id = objName + dstObjName;
      if( objName > dstObjName ){
        id = dstObjName + objName;
      }
      $("#" + id).remove();
      drawLine({
        ID: id,
        x1: objects[objName][0] + xCorrect,
        y1: objects[objName][1] + yCorrect,
        x2: objects[dstObjName][0] + xCorrect,
        y2: objects[dstObjName][1] + yCorrect
      });
    }    
  }
}
function drawLine(params) {
  var param = jQuery.extend({
              ID: 0
            , x1: 0
            , y1: 0
            , x2: 0
            , y2: 0
            , line_style: "solid"
            , line_color: "#aaaaaa"
            , line_width: "1px"
            , parent: $("body")
            , callback: function(){}
  }, params);
  if(param.x1 < param.x2){
    sx = param.x1;
    ex = param.x2;
    sy = param.y1;
    ey = param.y2;
  }
  else {
    sx = param.x2;
    ex = param.x1;
    sy = param.y2;
    ey = param.y1;
  }
  var w = Math.sqrt(Math.pow((sx - ex) ,2) + Math.pow((sy - ey) ,2));
  var base = Math.max(sx, ex) - Math.min(sx, ex);
  var tall = Math.max(sy, ey) - Math.min(sy, ey);
  var aTan = Math.atan(tall / base);
  var deg = aTan * 180 / Math.PI;
  deg = sy > ey ? 0 - deg: deg;
  var line = $("<div id=" + param.ID + "></div>")
    .addClass("line")
    .css({
      "left": sx,
      "top": sy,
      "width": w,
      "transform": "rotate(" + deg + "deg)",
      "-webkit-transform": "rotate(" + deg + "deg)",
      "border-top-style": param.line_style,
      "border-top-color": param.line_color,
      "border-top-width": param.line_width,
    });
  $(param.parent).append(line);
}
function dispJson() {
  alert(JSON.stringify(objects));
}
$(document).ready(function()
{
  // init draw objects
  init();
  $('.object').draggable({
    stop: function(){
      var ofs = $(this).offset();
      var objName = this.id;
      objects[objName][0] = ofs.left;
      objects[objName][1] = ofs.top;
      for(var i=0; i < objects[objName][2].length; ++i){
        var dstObjName = objects[objName][2][i];
        var id = objName + dstObjName;
        if( objName > dstObjName ){
          id = dstObjName + objName;
        }
        $("#" + id).remove();
        drawLine({
          ID: id,
          x1: objects[objName][0] + xCorrect,
          y1: objects[objName][1] + yCorrect,
          x2: objects[dstObjName][0] + xCorrect,
          y2: objects[dstObjName][1] + yCorrect
        });
      }    
    }
  });
});
</script>
</head>
<body>
<input type="button" value="disp objects at json" onClick="dispJson()">
</body>
</html>

 

Canvasを使わずラインを引く

コレ(http://king-of-nowhere.hatenablog.com/entry/2013/11/28/084116)スゴイです。

全てDIV要素1つで1つの線なので、#(ID).remove() や、 #(ID).css({}) で、ID毎に、線を消したり、移動したりと重なりを考慮しなくてよいので大変便利です。

<html>
<head>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<style>
.line{
    position: absolute;
    border-top: solid 1px #FF4981;
    -moz-transform-origin:0% 0%;
    -webkit-transform-origin:0% 0%;
    transform-origin:0% 0%;
    float: left;
}
</style>
<script>
function DrawLine(params) {
  var param = jQuery.extend({
              ID: 0
            , x1: 0
            , y1: 0
            , x2: 0
            , y2: 0
            , line_style: "solid"
            , line_color: "#000"
            , line_width: "1px"
            , parent: $("body")
            , callback: function(){}
  }, params);
  if(param.x1 < param.x2){
    sx = param.x1;
    sy = param.y1;
    ex = param.x2;
    ey = param.y2;
  }
  else {
    sx = param.x2;
    sy = param.y2;
    ex = param.x1;
    ey = param.y1;
  }
  var w = Math.sqrt(Math.pow((sx - ex) ,2) + Math.pow((sy - ey) ,2));
  var base = Math.max(sx, ex) - Math.min(sx, ex);
  var tall = Math.max(sy, ey) - Math.min(sy, ey);
  var aTan = Math.atan(tall / base);
  var deg = aTan * 180 / Math.PI;
  deg = sy > ey ? 0 - deg: deg;
  var line = $("<div id=" + param.ID + "></div>")
    .addClass("line")
    .css({
      "left": sx,
      "top": sy,
      "width": w,
      "transform": "rotate(" + deg + "deg)",
      "-webkit-transform": "rotate(" + deg + "deg)",
      "border-top-style": param.line_style,
      "border-top-color": param.line_color,
      "border-top-width": param.line_width,
    });
  $(param.parent).append(line);
}

$(document).ready(function()
{
  DrawLine({
    ID: "L2SW11P0-L2SW12P0",
    x1: 0,
    y1: 0,
    x2: 100,
    y2: 100,
  });
  DrawLine({
    ID: "L2SW11P1-L2SW12P1",
    x1: 100,
    y1: 100,
    x2: 200,
    y2: 0,
  });
  for(var i=0; i<=10; i++){
    $('#L2SW11P1-L2SW12P1').css({"left": 100 - i*10});
    alert();
  }
});
</script>
</head>
<body>
</body>
</html>

Xの値が、開始と終了の大きさが反転していると、おかしな動作になったので、必ず開始が小さくなるように条件分岐を入れてみました。