简体   繁体   中英

Draw line over divs

I would like to link two divs (left edge of a2 and left edge of b1 ) with line. I have found that one of the ways is to use svg element and I tried to do that in vain.

The expected result is: 在此处输入图片说明

There are two problems:

  1. The link has to be added dyamically so I tried to use javascript but something does not work. If I place the value of elementToAppend to the mySvg manually - the line display and there are two lines in the html source of the page but only one is displayed.

  2. If the line is added manually - the element fromElement is linked to the toElement with blue line. The problem is that this line is relative to the whole screen, not the container container that is scrollable (it has to be scrollable). So whe user scrolls the container - the line does not scroll and stay on the same place.

My code is:

<html>
    <head>
        <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>
    <body>
        <div id="customHeader">custom header</div>

        <div id="container"> 
            <div id="firstRow">
                <div class="elementA">a1</div>
                <div class="elementA">a2</div>
                <div id="fromElement" class="elementA">a3</div>
                <div class="elementA">a4</div>
                <div class="elementA">a5</div>
                <div class="elementA">a6</div>
                <div class="elementA">a7</div>
                <div class="elementA">a8</div>
                <div class="elementA">a9</div>
            </div>
            <div id="secondRow">
                <div class="elementB">b1</div>
                <div id="toElement" class="elementB">b2</div>
                <div class="elementB">b3</div>
                <div class="elementB">b4</div>
                <div class="elementB">b5</div>
                <div class="elementB">b6</div>
                <div class="elementB">b7</div>
                <div class="elementB">b8</div>
                <div class="elementB">b9</div>
            </div>      
        </div>
        <svg id="mySvg">
        </svg> 
    </body>
    
    <script>
        $(function(){
            linkElements();
        });
        
        function linkElements(){
            var fromHeight = $("#fromElement").position().top - $("#fromElement").height()/2;
            var fromLeft = $("#fromElement").position().left;
            var toHeight = $("#toElement").position().top - $("#toElement").height()/2;
            var toLeft = $("#toElement").position().left;
            var middleVertical = toHeight - fromHeight;
            var middleHorizontal = toLeft - fromLeft;
            var elementToAppend = "<path d='M " + fromLeft + " " + fromHeight + " L " + toLeft + " " + toHeight + "' stroke='blue' strine-width='5' fill='none' />";
            console.log(elementToAppend)
            $("#mySvg").append(elementToAppend);
        }
        
    </script>
    
    <style>
        #mySvg{
            position:absolute;
            top:0px;
            left:0px;
            width:100%;
            height:100%;
        }
        #customHeader{
            width: 100%;
            height: 100px;
            background: grey;
            text-align: center;
        }   
        #container{
            overflow: auto;
            display: flex;
            height: 500px;
        }
        #secondRow, #firstRow{
            float: left;
            flex: 1;
            height: 100%;
            margin-left: 20px;
            margin-right: 20px;
        }
        .elementA, .elementB{
            margin-top: 20px;
            margin-bottom: 20px;
            width: 100%;
            height: 100px;
            background: red;
            text-align: center;
        }
    </style>
</html>

What is the best way to solve that problem?

The problem is that the line linking two elements is showing when it is added manually, but not when it is added by Javascript. elementToAppend is actually a string, not an element object, so you don't want to append it into the SVG element, you need instead to put it into the SVG element's innerHTML.

So remove this line: $("#mySvg").append(elementToAppend);

and replace with: document.getElementById("mySvg").innerHTML = elementToAppend;

Also to recalculate the line when the window is altered an onresize event is senses in the body element.

 <html> <head> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> </head> <body onresize="linkElements()"> <div id="customHeader">custom header</div> <div id="container"> <div id="firstRow"> <div class="elementA">a1</div> <div class="elementA">a2</div> <div id="fromElement" class="elementA">a3</div> <div class="elementA">a4</div> <div class="elementA">a5</div> <div class="elementA">a6</div> <div class="elementA">a7</div> <div class="elementA">a8</div> <div class="elementA">a9</div> </div> <div id="secondRow"> <div class="elementB">b1</div> <div id="toElement" class="elementB">b2</div> <div class="elementB">b3</div> <div class="elementB">b4</div> <div class="elementB">b5</div> <div class="elementB">b6</div> <div class="elementB">b7</div> <div class="elementB">b8</div> <div class="elementB">b9</div> </div> </div> <svg id="mySvg"> </svg> </body> <script> $(function(){ linkElements(); }); function linkElements(){ var fromHeight = $("#fromElement").position().top - $("#fromElement").height()/2; var fromLeft = $("#fromElement").position().left; var toHeight = $("#toElement").position().top - $("#toElement").height()/2; var toLeft = $("#toElement").position().left; var middleVertical = toHeight - fromHeight; var middleHorizontal = toLeft - fromLeft; var elementToAppend = "<path d='M " + fromLeft + " " + fromHeight + " L " + toLeft + " " + toHeight + "' stroke='blue' strine-width='5' fill='none' />"; console.log(elementToAppend) //$("#mySvg").append(elementToAppend); document.getElementById("mySvg").innerHTML = elementToAppend; } </script> <style> #mySvg{ position:absolute; top:0px; left:0px; width:100%; height:100%; } #customHeader{ width: 100%; height: 100px; background: grey; text-align: center; } #container{ overflow: auto; display: flex; height: 500px; } #secondRow, #firstRow{ float: left; flex: 1; height: 100%; margin-left: 20px; margin-right: 20px; } .elementA, .elementB{ margin-top: 20px; margin-bottom: 20px; width: 100%; height: 100px; background: red; text-align: center; } </style> </html>

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