【问题标题】:Draw a line between 2 divs once 2 consequence div clicked using angularjs使用 angularjs 单击 2 个结果 div 后,在 2 个 div 之间画一条线
【发布时间】:2017-02-02 18:17:08
【问题描述】:

一旦用户单击,我有 2 个 DIV 需要用一条线连接。我以角度开发我的项目。谁能帮我?我真的需要解决方案。

查看我的 sn-p 以获得更清晰的信息。

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

【问题讨论】:

  • 到目前为止你尝试了什么,我可以看看你的完整代码吗?
  • 我做了一些研究……但主要使用jquery或jSPlumb……从头开始开发容易吗?我不知道如何开始lol hoho。
  • 由于 html 不提供开箱即用的此类功能,因此您必须发挥创意。我的方法是将 svg 作为绘图表面,驻留在必须连接的 div 下,然后在其上绘制连接线。
  • 每个 div 都来自 ng-repeat 数据。所以我首先需要将它转换为 SVG 以使其能够绘制?帆布怎么样?有可能吗?如果可以,那就更好了。
  • 如果你能告诉我如何使用 SVG 或画布来实现它......我真的很感激。

标签: javascript html css angularjs


【解决方案1】:

您可以在画布上下文中使用lineTo。详情请见https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D

首先,在 html 上定义一个画布:

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

那么你可以在上面画一条线:

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 getPoint(answerElement) {
    var roundPointer = answerElement.lastElementChild;

    return {
        y: answerElement.offsetTop + roundPointer.offsetTop + roundPointer.offsetHeight / 2,
        x: answerElement.offsetLeft + roundPointer.offsetLeft + roundPointer.offsetWidth / 2
    };
}

因此,您可以使用这两个函数获取“圆形指针”的中心点,并在画布中从它到另一个“圆形指针”绘制一条线,假设画布位于同一个答案容器的偏移父级上并且它的大小必须足够大。

接下来,您必须处理选择两个答案以将它们连接起来。下面有一个演示给你。如果您更改答案,此演示不会处理擦除一行。

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>

【讨论】:

  • 非常好...还有一件事..如何取消线路?
  • 您必须清除画布并重新绘制连接。
  • 嗨,你能帮我解决这个问题吗? stackoverflow.com/questions/39845688/…
  • 如何通过导入创建的json重绘相同的流程
【解决方案2】:

这是一个使用 SVG 的解决方案:

点击左右框后,它会在最后点击的两个元素之间画一条线。

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>

更新

我还添加了一个选项,可以在再次单击已经有一行的框时删除一行。

【讨论】:

  • 非常好!还有一件事..如果用户想要更改它,如何取消它?
  • 您可以保存添加到相关元素的行,一旦再次单击该元素 - 删除该行。
  • 对不起,我不清楚..它在你的小提琴中工作吗?
  • 不,它不在您的原始问题中。这是关于如何实现这一点的建议。
  • 是的,angular是一个javascript库,你可以使用它。
猜你喜欢
  • 2021-12-14
  • 1970-01-01
  • 2019-12-20
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-04
相关资源
最近更新 更多