在两个html元素之间绘制一个可弯曲的箭头

时间:2014-11-12 12:02:42

标签: javascript jquery html

我正在为我的网站中的某些项目开发视图。目前我有HTML中显示的项目,但现在我需要在表示它们之间的连接的元素之间绘制一些线条,它就像一个甘特图,但它不包括任何时间功能,我只需要连接项目与他们相关的。我正在使用JSTL从控制器中提取一些数据,我设法绘制如下图像的元素:http://i271.photobucket.com/albums/jj131/djrickel/before.png

我需要显示的方式如下图所示: http://i271.photobucket.com/albums/jj131/djrickel/after.png

这就是我创建包含我想要显示的元素的表格的方式:

    <div class="container">
        <table>
            <tbody>
                <c:forEach items="${nodeGraphs}" var="nodeGraph">
                    <tr>
                        <c:forEach var="i" begin="0" end="5">
                            <td>
                                <c:if test="${nodeGraph.columnID == i}">
                                    <label class="label label-default">${nodeGraph.nodeObject.item.type}${nodeGraph.nodeObject.item.contextId}</label>
                                </c:if>
                            </td>
                        </c:forEach>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </div>  

有没有人知道使用JQuery,JSon,Javascript或任何HTML进程在元素之间创建连接线的方法?我可以从我正在使用的表格改为div或span而没有任何问题。我只是在寻找显示信息的最佳方式。提前谢谢。

1 个答案:

答案 0 :(得分:0)

可能最好的方法是使用HTML5画布,但如果您想使用div,请尝试使用此代码:

(在JSFiddle上:http://fiddle.jshell.net/22rar61n/9/

&#13;
&#13;
var Line = (function() {

  var diff = function(a, b) {
    var d = Math.abs(a - b);
    if (d === 0) {
      d = 1;
    }
    return d;
  }

  var countWidth = function(line) {
    return diff(line.endX, line.startX);
  };

  var countHeight = function(line) {
    return diff(line.endY, line.startY);
  };

  var Line = function(options) {
    this.startX = options.startX;
    this.startY = options.startY;
    this.endX = options.endX;
    this.endY = options.endY;
  }

  Line.prototype.drowIn = function($container) {
    var self = this;
    var line = jQuery("<div></div>", {
      class: "line " + self.LineType(),
      css: {
        "color": "red",
        "top": self.startY,
        "left": self.startX,
        "width": countWidth(self),
        "height": countHeight(self),
        "background-color": "#000"
      }
    });

    $container.append(line);
  };

  Line.prototype.LineType = function() {
    if (this.startX != this.endX) {
      return "horizontal";
    }
    return "vertical";
  }

  return Line;
})();

var Arrow = (function() {
  var Arrow = function(start, end) {
    this.start = start;
    this.end = end;
  }

  Arrow.prototype.drowIn = function($container) {
    var ArrowContainer = jQuery("<div></div>", {
      class: "arrowContainer"
    });

    var line1 = new Line({
      startX: this.start.x,
      startY: this.start.y,
      endX: this.start.x,
      endY: this.end.y
    });
    line1.drowIn(ArrowContainer);

    var line2 = new Line({
      startX: this.start.x,
      startY: this.end.y,
      endX: this.end.x,
      endY: this.end.y
    });
    line2.drowIn(ArrowContainer);

    $container.append(ArrowContainer);
  }

  return Arrow;
})();

var Element = (function() {
  var Element = function(options) {
    var op = jQuery.extend({}, options);

    this.x = op.x || -1;
    this.y = op.y || -1;
    this.content = op.content || "";
    this.container = op.$container || "";
    this.node = null;
    this.subElements = [];
  };

  Element.prototype.addSubElement = function(element) {
    element.container = this.container;

    element.content = this.content + "." + (this.subElements.length + 1);
    this.subElements.push(element);
  };

  Element.prototype.drow = function() {
    var self = this;
    this.node = jQuery("<div></div>", {
      class: "element",
      text: this.content,
      css: {
        top: self.y,
        left: self.x
      }
    });

    this.container.append(this.node);
    var nexLvl = 0;
    var lastHeight = nexLvl;
    var lastLvl = 0;
    var oldIndex = -1;
    var outerHeightAndTop = jQuery(self.node).outerHeight() + jQuery(self.node).offset().top;

    jQuery.each(this.subElements, function(index, element) {
      var height = outerHeightAndTop * (index + 1 + lastLvl);
      if (lastHeight != 0) {
        height = lastHeight + outerHeightAndTop;
      }
      if (nexLvl != 0) {
        oldIndex = index;
        height = height + ((jQuery(self.node).outerHeight()) * nexLvl);
        lastLvl = nexLvl;
      }

      lastHeight = height;
      nexLvl = element.getMaxLevel();
      element.x = jQuery(self.node).outerWidth() + jQuery(self.node).offset().left;
      element.y = height;
      element.drow();
      self.connectWith(element);
    });
  };

  Element.prototype.connectWith = function(element) {
    var startY = jQuery(this.node).outerHeight() + this.y;
    var startX = (jQuery(this.node).outerWidth() / 2) + this.x;

    var endY = (jQuery(element.node).outerHeight() / 2) + element.y;
    var arrow = new Arrow({
      x: startX,
      y: startY
    }, {
      x: element.x,
      y: endY
    });
    arrow.drowIn(this.container);
  };

  function getLevelOnPosition(index) {
    return this.subElements[index].getMaxLevel();
  }

  Element.prototype.getMaxLevel = function(initLvl) {
    var lvl = initLvl || 0;
    var maxLvl = lvl;
    if (this.subElements.length > 0) {
      maxLvl = lvl++;
    }
    jQuery.each(this.subElements, function(index, element) {
      lvl = element.getMaxLevel(lvl);
      if (lvl > maxLvl) {
        maxLvl = lvl;
      }
    });
    return maxLvl;
  }

  return Element;
})();

jQuery(document).ready(function() {
  var container = jQuery("#container");


  var e = new Element({
    x: 10,
    y: 10,
    content: "a1",
    $container: container
  });

  var sube = new Element();
  e.addSubElement(sube);
  var sube2 = new Element();
  sube.addSubElement(sube2);
  sube2.addSubElement(new Element());
  var e2 = new Element();
  e.addSubElement(e2);
  e2.addSubElement(new Element());
  e.addSubElement(new Element());
  e.drow();
});
&#13;
#container {
  position: relative;
}
#container > .element {
  position: absolute;
  border: 1px solid black;
  background-color: gray;
  color: white;
  padding: 2px;
  z-index: 10;
}
#container > .arrowContainer {
  position: absolute;
}
#container > .arrowContainer > .line {
  position: absolute;
  z-index: 50;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container"></div>
&#13;
&#13;
&#13;

相关问题