I am trying to make a network-like design with div
s and connecting lines between every two divs
but when I used svg
and line
tags with the JS function below, the console showed an error saying that
position is not a function.
What is wrong with my code? How do I fix it or are there other ways to draw lines between two div
s?
**
The problem is solved but now I tried to use loops and arrays because if I connected all the divs manually it will take forever. so I wrote the code below but know it shows the same error again. I tried to put each element of the array in a variable but it also didn't work.
**
Here is the code:
```
$(function() {
var orgs = document.getElementsByClassName('org'),
lines = document.getElementsByClassName('con-line'),
org1,
org2,
line,
pos1,
pos2,
count = 0;
for (let i = 0; i < orgs.length; i ) {
org1 = orgs[i];
for (let j = 0; j < orgs.length; j ) {
org2 = orgs[j];
line = lines[count];
if (j != i)
{
pos1 = org1.position();
pos2 = org2.position();
line
.attr('x1', pos1.left)
.attr('y1', pos1.top)
.attr('x2', pos2.left)
.attr('y2', pos2.top)
.attr('stroke', 'red')
.attr('stroke-width', 2);
count ;
}
}
}
});
```
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
jQuery
Try to wrap your code into "document ready" construction. This will ensure that the code is executed after the jQuery is loaded.
Define the
stroke
andstroke-width
attributes to make the line visible.
$(function() {
var line1= $('#line1');
var div1 = $('#org1');
var div2 = $('#org2');
var l1pos1 = div1.position();
var l1pos2 = div2.position();
line1
.attr('x1', l1pos1.left)
.attr('y1', l1pos1.top)
.attr('x2', l1pos2.left)
.attr('y2', l1pos2.top)
.attr('stroke', 'red')
.attr('stroke-width', 10);
});
.con{
margin-top: 50px;
}
.con-title{
width: 100%;
text-align: center;
color: #4E4E50;
font-size: 40px;
font-weight: bold;
}
.org-map{
position: relative;
width: 300px;
height: 300px;
margin: 40px auto 0 auto;
}
.org{
position: absolute;
}
.org .org-box{
position: relative;
bottom: 0px;
width: 15px;
height: 15px;
border-radius: 20px;
background: #4E4E50;
transition: 0.6s;
}
#org1{
transform: translate(-50%, 0%);
bottom: 80%;
left: 50%;
}
#org2{
transform: translate(-50%, 0%);
bottom: 65%;
left: 20%;
}
#org3{
transform: translate(-50%, 0%);
bottom: 35%;
left: 20%;
}
#org4{
transform: translate(-50%, 0%);
bottom: 50%;
left: 50%;
}
#org5{
transform: translate(-50%, 0%);
bottom: 65%;
left: 80%;
}
#org6{
transform: translate(-50%, 0%);
bottom: 35%;
left: 80%;
}
#org7{
transform: translate(-50%, 0%);
bottom: 20%;
left: 50%;
}
.org:hover .org-box{
background: #C3073F;
animation: org 1s;
animation-fill-mode: forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="con">
<div class="con-title">Contributions</div>
<div class="org-map">
<div class="org" id="org1">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org2">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org3">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org4">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org5">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org6">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org7">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<svg width="500" height="500">
<line id="line1"/>
<line id="line2"/>
</svg>
</div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Pure JavaScript
You can use the Element.getBoundingClientRect() method to get more information about
div
blocks.In this case, in the calculations, it is necessary to take into account the position of the SVG element itself. To do this, we subtract from the absolute coordinates of the points the corresponding coordinates of the upper left corner of the SVG.
This is an example of the JavaScript code without jQuery:
let line1 = document.getElementById('line1');
let svgRect = document.getElementById('lines').getBoundingClientRect();
let rect1 = document.getElementById('org1').getBoundingClientRect();
let rect2 = document.getElementById('org2').getBoundingClientRect();
let dot1x = (rect1.left rect1.right) / 2;
let dot1y = (rect1.top rect1.bottom) / 2;
let dot2x = (rect2.left rect2.right) / 2;
let dot2y = (rect2.top rect2.bottom) / 2;
setAttributes(line1, {
'x1': dot1x - svgRect.left,
'y1': dot1y - svgRect.top,
'x2': dot2x - svgRect.left,
'y2': dot2y - svgRect.top,
'stroke': 'red',
'stroke-width': 4,
});
// helper function from https://stackoverflow.com/a/12274782/6263942
function setAttributes(el, attrs) {
for(var key in attrs) {
el.setAttribute(key, attrs[key]);
}
}
.con {
margin-top: 50px;
}
.con-title {
width: 100%;
text-align: center;
color: #4E4E50;
font-size: 40px;
font-weight: bold;
}
.org-map {
position: relative;
width: 300px;
height: 300px;
margin: 40px auto 0 auto;
}
.org {
position: absolute;
}
.org .org-box {
position: relative;
bottom: 0px;
width: 15px;
height: 15px;
border-radius: 20px;
background: #4E4E50;
transition: 0.6s;
}
#org1 {
transform: translate(-50%, 0%);
bottom: 80%;
left: 50%;
}
#org2 {
transform: translate(-50%, 0%);
bottom: 65%;
left: 20%;
}
#org3 {
transform: translate(-50%, 0%);
bottom: 35%;
left: 20%;
}
#org4 {
transform: translate(-50%, 0%);
bottom: 50%;
left: 50%;
}
#org5 {
transform: translate(-50%, 0%);
bottom: 65%;
left: 80%;
}
#org6 {
transform: translate(-50%, 0%);
bottom: 35%;
left: 80%;
}
#org7 {
transform: translate(-50%, 0%);
bottom: 20%;
left: 50%;
}
.org:hover .org-box {
background: #C3073F;
animation: org 1s;
animation-fill-mode: forwards;
}
<div class="con">
<div class="con-title">Contributions</div>
<div class="org-map">
<div class="org" id="org1">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org2">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org3">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org4">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org5">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org6">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<div class="org" id="org7">
<div class="org-box">
<img src="" alt="">
</div>
</div>
<svg width="500" height="500" id="lines">
<line id="line1"/>
<line id="line2"/>
</svg>
</div>
</div>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>