Menggambar garis penghubung antara dua elemen [tertutup]

106

Bagaimana cara menggambar garis antara dua atau lebih elemen untuk menghubungkannya? Kombinasi HTML / CSS / JavaScript / SVG / Canvas baik-baik saja.

Jika jawaban Anda mendukung semua ini, sebutkan:

  • elemen yang dapat diseret
  • koneksi yang dapat diseret / diedit
  • elemen penghindaran tumpang tindih

Pertanyaan ini telah diperbarui untuk menggabungkan berbagai variasinya .

Bakhtiyor
sumber

Jawaban:

164

jsPlumb adalah opsi yang tersedia yang mendukung seret dan lepas, seperti yang terlihat pada banyak demo , termasuk demo Diagram Alir .

Ini tersedia dalam edisi Komunitas gratis, dan edisi Toolkit berbayar.

Edisi Toolkit membungkus edisi Komunitas dengan lapisan data binding yang komprehensif, serta beberapa widget UI untuk membangun aplikasi dan integrasi untuk perpustakaan populer, dan memiliki lisensi komersial.

Tomasz Kowalczyk
sumber
4
Toolkit luar biasa tetapi berhati-hatilah: ini tidak gratis! Mereka ingin Anda membeli lisensi jika Anda bermaksud menjadi tuan rumah untuk umum atau menjual dalam produk Anda sendiri (lihat jsplumbtoolkit.com/purchase ).
Chris
50

Menggabungkan garis dengan svg sangat berharga untuk saya, dan bekerja dengan sempurna ... pertama-tama, Scalable Vector Graphics (SVG) adalah format gambar vektor berbasis XML untuk grafik dua dimensi dengan dukungan untuk interaktivitas dan animasi. Gambar SVG dan perilakunya ditentukan dalam file teks XML. Anda dapat membuat svg dalam HTML menggunakan <svg>tag. Adobe Illustrator adalah salah satu perangkat lunak terbaik yang digunakan untuk membuat svg kompleks menggunakan jalur.

Prosedur untuk menggabungkan dua div menggunakan sebuah baris:

  1. buat dua div dan beri mereka posisi apa pun yang Anda butuhkan

    <div id="div1" style="width: 100px; height: 100px; top:0; left:0; background:#e53935 ; position:absolute;"></div>
    <div id="div2" style="width: 100px; height: 100px; top:0; left:300px; background:#4527a0 ; position:absolute;"></div>
    

    (demi penjelasan, saya melakukan beberapa gaya sebaris tetapi selalu baik untuk membuat file css terpisah untuk penataan gaya)

  2. <svg><line id="line1"/></svg>

    Tag garis memungkinkan kita menggambar garis antara dua titik tertentu (x1, y1) dan (x2, y2). (untuk referensi kunjungi w3schools.) kita belum menentukannya. karena kita akan menggunakan jQuery untuk mengedit atribut (x1, y1, x2, y2) dari tag baris.

  3. dalam <script>menulis tag

    line1 = $('#line1');   
    div1 = $('#div1');   
    div2 = $('#div2');
    

    Saya menggunakan penyeleksi untuk memilih dua div dan baris ...

    var pos1 = div1.position();
    var pos2 = div2.position();
    

    position()Metode jQuery memungkinkan kita mendapatkan posisi elemen saat ini. Untuk informasi lebih lanjut, kunjungi https://api.jquery.com/position/ (Anda juga dapat menggunakan offset()metode)

Sekarang setelah kita mendapatkan semua posisi yang kita butuhkan, kita dapat menggambar garis sebagai berikut ...

line1
  .attr('x1', pos1.left)
  .attr('y1', pos1.top)
  .attr('x2', pos2.left)
  .attr('y2', pos2.top);

.attr()Metode jQuery digunakan untuk mengubah atribut elemen yang dipilih.

Yang kami lakukan di baris di atas adalah mengubah atribut baris dari

x1 = 0
y1 = 0
x2 = 0
y2 = 0

untuk

x1 = pos1.left
y1 = pos1.top
x2 = pos2.left
y2 = pos2.top

karena position()mengembalikan dua nilai, satu 'kiri' dan 'atas' lainnya, kita dapat dengan mudah mengaksesnya menggunakan .top dan .left menggunakan objek (di sini pos1 dan pos2) ...

Sekarang tag garis memiliki dua koordinat berbeda untuk menarik garis di antara dua titik.

Tip: tambahkan event listener saat Anda membutuhkan div

Tip: pastikan Anda mengimpor pustaka jQuery terlebih dahulu sebelum menulis apa pun di tag skrip

Setelah menambahkan koordinat melalui JQuery ... Ini akan terlihat seperti ini

Cuplikan berikut hanya untuk tujuan demonstrasi, harap ikuti langkah-langkah di atas untuk mendapatkan solusi yang tepat

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1" style="width: 100px; height: 100px; top:0; left:0; background:#e53935 ; position:absolute;"></div>
<div id="div2" style="width: 100px; height: 100px; top:0; left:300px; background:#4527a0 ; position:absolute;"></div>
<svg width="500" height="500"><line x1="50" y1="50" x2="350" y2="50" stroke="red"/></svg>

Ani
sumber
3
Harap jangan menyalin dan menempel jawaban yang sama untuk beberapa pertanyaan. Sebaliknya, sesuaikan jawaban untuk setiap pertanyaan.
Andy
2
Saya perlu meletakkan svg dengan lebar dan tinggi 100% di latar belakang menggunakan z-index -1 tetapi itu berfungsi seperti pesona.
steven
4
Jawaban ini disalin dari stackoverflow.com/questions/19382872/…
Damjan Pavlica
31
Downvoters, tolong beri komentar alasan melakukannya ... Saya telah memposting jawaban yang sama untuk kedua pertanyaan karena saya yakin jawaban ini berlaku untuk kedua pertanyaan ... Jika dua pertanyaan relevan maka jawaban mereka juga bisa relevan .. Saya tidak melakukan sesuatu yang salah ...
Ani
6

Saya juga memiliki persyaratan yang sama beberapa hari yang lalu

Saya menggunakan lebar penuh dan tinggi svg dan menambahkannya di bawah semua div saya dan menambahkan baris ke svg ini secara dinamis.

Lihat bagaimana saya melakukannya di sini menggunakan svg

HTML

<div id="ui-browser"><div class="anchor"></div>
     <div id="control-library" class="library">
       <div class="name-title">Control Library</div>
       <ul>
         <li>Control A</li>
         <li>Control B</li>
         <li>Control C</li>
         <li>Control D</li>
       </ul>
     </div><!--
--></div><!--
--><div id="canvas">
     <svg id='connector_canvas'></svg>
     <div class="ui-item item-1"><div class="con_anchor"></div></div>
     <div class="ui-item item-2"><div class="con_anchor"></div></div>
     <div class="ui-item item-3"><div class="con_anchor"></div></div>
     <div class="ui-item item-1"><div class="con_anchor"></div></div>
     <div class="ui-item item-2"><div class="con_anchor"></div></div>
     <div class="ui-item item-3"><div class="con_anchor"></div></div>
   </div><!--
--><div id="property-browser"></div>

https://jsfiddle.net/kgfamo4b/

    $('.anchor').on('click',function(){
   var width = parseInt($(this).parent().css('width'));
   if(width==10){
     $(this).parent().css('width','20%');
     $('#canvas').css('width','60%');
   }else{
      $(this).parent().css('width','10px');
     $('#canvas').css('width','calc( 80% - 10px)');
   }
});

$('.ui-item').draggable({
  drag: function( event, ui ) {
           var lines = $(this).data('lines');
           var con_item =$(this).data('connected-item');
           var con_lines = $(this).data('connected-lines');

           if(lines) {
             lines.forEach(function(line,id){
                    $(line).attr('x1',$(this).position().left).attr('y1',$(this).position().top+1);  
             }.bind(this));
           }

           if(con_lines){
               con_lines.forEach(function(con_line,id){
                  $(con_line).attr('x2',$(this).position().left)
                        .attr('y2',$(this).position().top+(parseInt($(this).css('height'))/2)+(id*5));
               }.bind(this));

           }

       }
});

$('.ui-item').droppable({
  accept: '.con_anchor',
  drop: function(event,ui){
     var item = ui.draggable.closest('.ui-item');
     $(this).data('connected-item',item);
     ui.draggable.css({top:-2,left:-2});
     item.data('lines').push(item.data('line'));

     if($(this).data('connected-lines')){
        $(this).data('connected-lines').push(item.data('line'));

         var y2_ = parseInt(item.data('line').attr('y2'));
         item.data('line').attr('y2',y2_+$(this).data('connected-lines').length*5);

     }else $(this).data('connected-lines',[item.data('line')]);

     item.data('line',null);
    console.log('dropped');
  }
});


$('.con_anchor').draggable({drag: function( event, ui ) {
     var _end = $(event.target).parent().position();
     var end = $(event.target).position();
     if(_end&&end)  
     $(event.target).parent().data('line')
                                                    .attr('x2',end.left+_end.left+5).attr('y2',end.top+_end.top+2);
},stop: function(event,ui) {
        if(!ui.helper.closest('.ui-item').data('line')) return;
        ui.helper.css({top:-2,left:-2});
        ui.helper.closest('.ui-item').data('line').remove();
        ui.helper.closest('.ui-item').data('line',null);
        console.log('stopped');
      }
});


$('.con_anchor').on('mousedown',function(e){
    var cur_ui_item = $(this).closest('.ui-item');
    var connector = $('#connector_canvas');
    var cur_con;

  if(!$(cur_ui_item).data('lines')) $(cur_ui_item).data('lines',[]);

  if(!$(cur_ui_item).data('line')){
         cur_con = $(document.createElementNS('http://www.w3.org/2000/svg','line'));
         cur_ui_item.data('line',cur_con);
    } else cur_con = cur_ui_item.data('line');

    connector.append(cur_con);
    var start = cur_ui_item.position();
     cur_con.attr('x1',start.left).attr('y1',start.top+1);
     cur_con.attr('x2',start.left+1).attr('y2',start.top+1);
});
Nadir Laskar
sumber
Sepertinya tidak berfungsi pada Safari Versi 12.0.1 (14606.2.104.1.1)
balupton
2

Baru-baru ini, saya mencoba mengembangkan aplikasi web sederhana yang menggunakan komponen seret dan lepas dan memiliki garis yang menghubungkannya. Saya menemukan dua pustaka javascript yang sederhana dan menakjubkan ini:

  1. Plain Draggable : pustaka sederhana dan berperforma tinggi untuk memungkinkan elemen HTML / SVG diseret.
  2. Garis Pemimpin : Buat garis pemimpin di halaman web Anda
Kerub
sumber
1

D3 memiliki ratusan contoh , beberapa di antaranya cocok untuk pertanyaan ini.

Contoh tanpa seret dan lepas, yang sudah diperbaiki:

Contoh tanpa drag and drop, yaitu interaktif:

Contoh dengan menyeret dan melepas:

Jawaban ini didasarkan pada jawaban Glenn Dayton .

balupton
sumber
1

js-graph.it mendukung kasus penggunaan ini, seperti yang terlihat pada panduan memulai , mendukung elemen menyeret tanpa tumpang tindih koneksi. Sepertinya tidak mendukung pengeditan / pembuatan koneksi. Sepertinya tidak dipertahankan lagi.

balupton
sumber