Draw a line between two divs as soon as 2 div key is pressed using angularjs

I have two DIVs that need to be connected to the same line after clicking the button. I am developing my project in angular. Can someone help me? I really need a solution.

See my fragment for more details.

.padding-answer-line-mapping { padding-bottom:8px; } .answer-container { width:40px; height:40px; background-color:#ccc; border:1px solid #ccc; margin:2px; float:left; text-align:center; padding-top:8px; cursor:pointer; position:relative; } .answer-container:hover, .answer-container:focus, .answer-container:active { background-color: #0076e9; color: white; border: 1px solid #0076e9; } .round-pointer-right { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; right:0px; top:14px; margin-right:-20px; } .round-pointer-left { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; left:0px; top:14px; margin-left:-20px; } 
 <link href="http://code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet"/> Match the following items. <div class="row padding-answer-line-mapping"> <div class="col answer-container"> One <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container"> 2 <div class="round-pointer-left"></div> </div> </div> <div class="row padding-answer-line-mapping"> <div class="col answer-container"> Two <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container"> 1 <div class="round-pointer-left"></div> </div> </div> 
+6
source share
3 answers

You can use lineTo from the canvas context. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D for more details.

First you define the canvas in html:

 <canvas id="connection-canvas"></canvas> 

Then you can draw a line on it:

 function drawLine(p1, p2) { var canvas = document.getElementById("connection-canvas"); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } 

All you need to do is figure out the offset of your circular pointers:

 function getPoint(answerElement) { var roundPointer = answerElement.lastElementChild; return { y: answerElement.offsetTop + roundPointer.offsetTop + roundPointer.offsetHeight / 2, x: answerElement.offsetLeft + roundPointer.offsetLeft + roundPointer.offsetWidth / 2 }; } 

Thus, you can use these two functions to get the center point of the “circular pointer” and draw a line in the canvas from it to the other “circular pointer”, assuming that the canvas is located on the same parent offset container and its size should be big enough.

Then you will need to select two answers to connect them. Below is a demo. This demo does not handle erasing a line if you change the answer.

 var lastSelection; // Add click listener for answer-container function listenToClick() { var rows = document.querySelectorAll('.row'), row; var cols, col; for (row = 0; row < rows.length; row++) { cols = rows[row].children; for (col = 0; col < cols.length; col++) { // Bind information about which answer is this, // so we can prevent from connecting two answers on // same column. cols[col].addEventListener('click', selectAnswer.bind({ row: row, col: col, element: cols[col] })); } } } // This is fired when a answer-container is clicked. function selectAnswer(event) { if (lastSelection) { lastSelection.element.classList.remove('selected'); } if (!lastSelection || lastSelection.col === this.col) { lastSelection = this; this.element.classList.add('selected'); } else { drawLine(getPoint(this.element), getPoint(lastSelection.element)); lastSelection = null; } } function getPoint(answerElement) { var roundPointer = answerElement.lastElementChild; return { y: answerElement.offsetTop + roundPointer.offsetTop + roundPointer.offsetHeight / 2, x: answerElement.offsetLeft + roundPointer.offsetLeft + roundPointer.offsetWidth / 2 }; } function drawLine(p1, p2) { var canvas = document.getElementById("connection-canvas"); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } function resizeCanvas() { var canvas = document.getElementById("connection-canvas"); var ctx = canvas.getContext("2d"); ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; } listenToClick(); resizeCanvas(); 
 .padding-answer-line-mapping { padding-bottom:8px; } .answer-container { width:40px; height:40px; background-color:#ccc; border:1px solid #ccc; margin:2px; float:left; text-align:center; padding-top:8px; cursor:pointer; position:relative; } .answer-container:hover, .answer-container:focus, .answer-container:active { background-color: #0076e9; color: white; border: 1px solid #0076e9; } .round-pointer-right { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; right:0px; top:14px; margin-right:-20px; } .round-pointer-left { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; left:0px; top:14px; margin-left:-20px; } .selected { background-color: red; } 
 <link href="//code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet"/> Match the following items. <canvas id="connection-canvas" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0"></canvas> <div class="row padding-answer-line-mapping"> <div class="col answer-container"> One <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container"> 2 <div class="round-pointer-left"></div> </div> </div> <div class="row padding-answer-line-mapping"> <div class="col answer-container"> Two <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container"> 1 <div class="round-pointer-left"></div> </div> </div> 
+5
source

Here is a solution using SVG:

As soon as the left and right boxes are clicked, he will draw a line between the last two elements that are clicked.

 var leftEl, rightEl; function drawLine(leftEl, rightEl) { var width = $(rightEl).offset().left - $(leftEl).offset().left; var height = $(leftEl).offset().top - $(rightEl).offset().top; if (height == 0) { height = 2; } var line = $("<div style='position: absolute; width: "+Math.abs(width)+"px; height: "+Math.abs(height)+"px;'><svg style='width: 100%; height: 100%;'><line x1='"+(height > 0 ? '0' : '100%')+"' y1='100%' ' x2='"+(height > 0 ? '100%' : '0')+"' y2='0' style='stroke:rgb(255,0,0);stroke-width:2'/></svg></div>"); $('.container').append(line); myPos = height > 0 ? 'left bottom' : 'left top'; ofPos = height == 2 ? 'center center-12' : 'left+5 top+5' if (leftEl.data('line')) { leftEl.data('line').remove() } if (rightEl.data('line')) { rightEl.data('line').remove() } line.position({ my: myPos, at: ofPos, of: leftEl }) leftEl.data('line', line) rightEl.data('line', line) } $('.box-left,.box-right').on('click', function() { if ($(this).hasClass('box-left')) { leftEl = this } if($(this).hasClass('box-right')) { rightEl = this } if (leftEl && rightEl) { drawLine( $(leftEl).parent().find('.round-pointer-right'), $(rightEl).parent().find('.round-pointer-left') ); leftEl = rightEl = null; } }); 
 .container { position: relative; } .padding-answer-line-mapping { padding-bottom:8px; } .answer-container { width:40px; height:40px; background-color:#ccc; border:1px solid #ccc; margin:2px; float:left; text-align:center; padding-top:8px; cursor:pointer; position:relative; } .answer-container:hover, .answer-container:focus, .answer-container:active { background-color: #0076e9; color: white; border: 1px solid #0076e9; } .round-pointer-right { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; right:0px; top:14px; margin-right:-20px; } .round-pointer-left { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; left:0px; top:14px; margin-left:-20px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" /> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <link href="http://code.ionicframework.com/1.3.1/css/ionic.css" rel="stylesheet"/> Match the following items. <div class="container"> <div class="row padding-answer-line-mapping"> <div class="col answer-container box-left"> One <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container box-right"> 2 <div class="round-pointer-left"></div> </div> </div> <div class="row padding-answer-line-mapping"> <div class="col answer-container box-left"> Two <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container box-right"> 1 <div class="round-pointer-left"></div> </div> </div> <div class="row padding-answer-line-mapping"> <div class="col answer-container box-left"> Three <div class="round-pointer-right"></div> </div> <div class="col"> </div> <div class="col answer-container box-right"> 3 <div class="round-pointer-left"></div> </div> </div> </div> 

Update

I also added the ability to delete a row as soon as a box that already has a row was pressed again.

+5
source

 var lastSelection; // Add click listener for answer-container function listenToClick() { var rows = document.querySelectorAll('.task'), row; var tasks, task; for (row = 0; row < rows.length; row++) { tasks = rows[row].children; for (task = 0; task < tasks.length; task++) { // Bind information about which answer is this, // so we can prevent from connecting two answers on // same column. tasks[task].addEventListener('click', selectAnswer.bind({ row: row, // task: task, element: tasks[task] })); } } } // This is fired when a answer-container is clicked. function selectAnswer(event) { if (lastSelection) { lastSelection.element.classList.remove('selected'); } if (!lastSelection || lastSelection.element === this.element) { lastSelection = this; this.element.classList.add('selected'); console.log( getPoint(this.element.parentNode,this.element)); } else { var StartIsBegin = lastSelection.element.classList.contains('round-pointer-begin') ? 1 : -1 ; var FinishIsBegin = this.element.classList.contains('round-pointer-begin') ? 1 : -1 ; drawArrow(getPoint(this.element.parentNode,this.element), getPoint(lastSelection.element.parentNode,lastSelection.element),StartIsBegin, FinishIsBegin); lastSelection = null; } } function getPoint(answerElement,roundPointer) { return { y: answerElement.offsetTop + roundPointer.offsetTop + roundPointer.offsetHeight / 2, x: answerElement.offsetLeft + roundPointer.offsetLeft + roundPointer.offsetWidth / 2 }; } function drawArrow(p2, p1,StartIsBegin , FinishIsBegin) { var canvas = document.getElementById("connection-canvas"); var ctx = canvas.getContext("2d"); var offset = 15 ; console.log(StartIsBegin, FinishIsBegin) var size = 9; var acuity = size/2; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p1.x-offset*StartIsBegin, p1.y); ctx.lineTo(p1.x-offset*StartIsBegin, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x-offset*FinishIsBegin, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x-offset*FinishIsBegin, p2.y); ctx.lineTo(p2.x, p2.y); ctx.stroke() // spearhead :)) ctx.fillStyle = 'green'; ctx.beginPath(); ctx.moveTo(p2.x, p2.y); ctx.lineTo(p2.x - size * FinishIsBegin, p2.y + size -acuity); ctx.lineTo(p2.x - size * FinishIsBegin, p2.y - size + acuity); ctx.lineTo(p2.x, p2.y); ctx.fill(); ctx.stroke(); /* Three Line ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p1.x+offset, p1.y); ctx.lineTo(p1.x+offset, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x-offset, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x-offset, p2.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); */ /* Two Line ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p1.x, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x, p1.y + ( (p2.y-p1.y)/2)); ctx.lineTo(p2.x, p2.y); ctx.stroke(); */ /* One Line ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p1.x, p2.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); */ } function resizeCanvas() { var canvas = document.getElementById("connection-canvas"); var ctx = canvas.getContext("2d"); ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; } resizeCanvas(); listenToClick(); 
 .padding-answer-line-mapping { padding-bottom:8px; } .answer-container { width:40px; height:40px; background-color:#ccc; border:1px solid #ccc; margin:2px; float:left; text-align:center; padding-top:8px; cursor:pointer; position:relative; margin-left: 200px; padding-left: 200px; } .answer-container2 { width:40px; height:40px; background-color:#ccc; border:1px solid #ccc; float:left; text-align:center; padding-top:8px; cursor:pointer; position:relative; margin-left: 200px; padding-left: 200px; margin-top: 200px; } .port:hover, .port:focus, .port:active { background-color: #0076e9; color: white; border: 1px solid #0076e9; } .port.round-pointer-end { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; right:0px; top:14px; margin-right:-20px; } .port.round-pointer-begin { position: absolute; background-color:#ccc; cursor:pointer; width:10px; height:10px; border-radius: 50%; left:0px; top:14px; margin-left:-20px; } .selected { background-color: red !important; } 
 <!DOCTYPE html> <html lang="ru"> <head> </head> <body> <canvas id="connection-canvas" style="width:500; height:300; position: absolute; top: 0; left: 0; right: 0; bottom: 0"></canvas> <div class="row padding-answer-line-mapping"> <div class="task answer-container"> One <div class="port round-pointer-begin"></div> <div class="port round-pointer-end"></div> </div> <div class="task answer-container2" > 2 <div class="port round-pointer-begin"></div> <div class="port round-pointer-end"></div> </div> </div> <div class="row padding-answer-line-mapping"> <div class="task answer-container"> Two <div class="port round-pointer-begin"></div> <div class="port round-pointer-end"></div> </div> <div class="task answer-container2"> 1 <div class="port round-pointer-begin"></div> <div class="port round-pointer-end"></div> </div> </div> <script type='text/javascript' src="arrow.js"></script> <link href="arrow.css" rel="stylesheet"/> </body> </html> 

A New Look

0
source

All Articles