简体   繁体   中英

Draw a bendable arrow between two html elements

I am developing a view for some items in my web site. Currently I have the items displayed in the HTML but now I need to draw some lines between the elements that will represent a connection between them, it's like a Gantt Chart but it doesn't include any time functionality, I only need to connect the items with the ones associated to them. I'm using JSTL to bring some data from a controller and I managed to draw the elements like the following image: http://i271.photobucket.com/albums/jj131/djrickel/before.png

And the way I need to display is in the following image: http://i271.photobucket.com/albums/jj131/djrickel/after.png

This is how I'm creating my table containing the elements that I want to display:

    <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>  

Does anyone know a way to create connecting lines between the elements using JQuery, JSon, Javascript or any HTML process? I can change from the table I'm using to div or span without any issue. I'm just looking the best way to display the information. Thanks in advance.

Probably the best way to do that is use HTML5 canvas, but if You want use div's try use this code:

(On JSFiddle: http://fiddle.jshell.net/22rar61n/9/ )

 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(); }); 
 #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; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="container"></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM