|
19 | 19 | </nav> |
20 | 20 |
|
21 | 21 | <main class="h-100 pos-relative pattern-grid-dot"> |
22 | | - <div data-role="linked-block, draggable" id="block1"> |
| 22 | + <div data-role="linked-block, draggable" id="block1" data-on-drag-move="dragBlock1" data-on-drag-stop="dragBlock1"> |
23 | 23 | <div class="north-side"></div> |
24 | 24 | <div class="east-side"> |
25 | | - <div class="link-point"></div> |
| 25 | + <div class="link-point" id="block1_a"></div> |
| 26 | + </div> |
| 27 | + <div class="south-side"> |
| 28 | + <div class="link-point" id="block1_b"></div> |
26 | 29 | </div> |
27 | | - <div class="south-side"></div> |
28 | 30 | <div class="west-side"></div> |
29 | 31 | </div> |
30 | 32 |
|
31 | | - <div data-role="linked-block, draggable" id="block2"> |
| 33 | + <div data-role="linked-block, draggable" id="block2" data-on-drag-move="dragBlock2" data-on-drag-stop="dragBlock2"> |
32 | 34 | <div class="north-side"></div> |
33 | 35 | <div class="east-side"></div> |
34 | 36 | <div class="south-side"></div> |
35 | 37 | <div class="west-side"> |
36 | | - <div class="link-point"></div> |
| 38 | + <div class="link-point" id="block2_a"></div> |
| 39 | + </div> |
| 40 | + </div> |
| 41 | + |
| 42 | + <div data-role="linked-block, draggable" id="block3" data-on-drag-move="dragBlock3" data-on-drag-stop="dragBlock3"> |
| 43 | + <div class="north-side"> |
| 44 | + <div class="link-point" id="block3_a"></div> |
37 | 45 | </div> |
| 46 | + <div class="east-side"></div> |
| 47 | + <div class="south-side"></div> |
| 48 | + <div class="west-side"></div> |
38 | 49 | </div> |
| 50 | + |
| 51 | +<!-- <svg class="connection-line" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;">--> |
| 52 | +<!-- <line id="connector" stroke="var(--linked-block-border-color)" stroke-width="1"/>--> |
| 53 | +<!-- </svg>--> |
| 54 | + |
| 55 | + <svg id="line-block1-block2" class="connection-line"> |
| 56 | + <path class="cl-curve" stroke="var(--linked-block-border-color)" stroke-width="2" fill="none"/> |
| 57 | + </svg> |
| 58 | + |
| 59 | + <svg id="line-block1-block3" class="connection-line"> |
| 60 | + <path class="cl-curve" stroke="var(--linked-block-border-color)" stroke-width="2" fill="none"/> |
| 61 | + </svg> |
39 | 62 | </main> |
40 | 63 |
|
41 | 64 | <script src="../lib/metro.js"></script> |
42 | 65 | <script> |
43 | | - (() => { |
44 | | - setTimeout(() => { |
45 | | - const block1 = $("#block1") |
46 | | - const block2 = $("#block2") |
47 | | - const parent = $("main") |
48 | | - |
49 | | - block1.css({ |
50 | | - top: parent.height() / 2 - block1.height() / 2, |
51 | | - left: parent.width() / 2 - block1.width() / 2 - 200, |
52 | | - }) |
53 | | - |
54 | | - block2.css({ |
55 | | - top: parent.height() / 2 - block2.height() / 2, |
56 | | - left: parent.width() / 2 - block2.width() / 2 + 200, |
57 | | - }) |
58 | | - }, 100) |
59 | | - })() |
| 66 | + // line |
| 67 | + // function updateConnection () { |
| 68 | + // const point1 = $('#block1_a') |
| 69 | + // const point2 = $('#block2_a') |
| 70 | + // const line = $('#connector') |
| 71 | + // const svg = $('.connection-line') |
| 72 | + // |
| 73 | + // // Отримуємо позиції точок відносно документа |
| 74 | + // const rect1 = point1.offset() |
| 75 | + // const rect2 = point2.offset() |
| 76 | + // |
| 77 | + // // Отримуємо позицію SVG контейнера відносно документа |
| 78 | + // const svgRect = svg.offset() |
| 79 | + // |
| 80 | + // // Отримуємо розміри точок для центрування |
| 81 | + // const point1Width = point1.outerWidth() |
| 82 | + // const point1Height = point1.outerHeight() |
| 83 | + // const point2Width = point2.outerWidth() |
| 84 | + // const point2Height = point2.outerHeight() |
| 85 | + // |
| 86 | + // // Розраховуємо координати відносно SVG контейнера і центруємо точки |
| 87 | + // const x1 = rect1.left - svgRect.left + point1Width / 2 |
| 88 | + // const y1 = rect1.top - svgRect.top + point1Height / 2 |
| 89 | + // const x2 = rect2.left - svgRect.left + point2Width / 2 |
| 90 | + // const y2 = rect2.top - svgRect.top + point2Height / 2 |
| 91 | + // |
| 92 | + // line.attr({ |
| 93 | + // x1: x1, |
| 94 | + // y1: y1, |
| 95 | + // x2: x2, |
| 96 | + // y2: y2 |
| 97 | + // }) |
| 98 | + // } |
| 99 | + |
| 100 | + // curve z |
| 101 | + // function updateConnection () { |
| 102 | + // const point1 = $('#block1_a') |
| 103 | + // const point2 = $('#block2_a') |
| 104 | + // const path = $('#connector') |
| 105 | + // const svg = $('.connection-line') |
| 106 | + // |
| 107 | + // const rect1 = point1.offset() |
| 108 | + // const rect2 = point2.offset() |
| 109 | + // const svgRect = svg.offset() |
| 110 | + // |
| 111 | + // const point1Width = point1.outerWidth() |
| 112 | + // const point1Height = point1.outerHeight() |
| 113 | + // const point2Width = point2.outerWidth() |
| 114 | + // const point2Height = point2.outerHeight() |
| 115 | + // |
| 116 | + // const x1 = rect1.left - svgRect.left + point1Width / 2 |
| 117 | + // const y1 = rect1.top - svgRect.top + point1Height / 2 |
| 118 | + // const x2 = rect2.left - svgRect.left + point2Width / 2 |
| 119 | + // const y2 = rect2.top - svgRect.top + point2Height / 2 |
| 120 | + // |
| 121 | + // let pathData = '' |
| 122 | + // |
| 123 | + // const tolerance = 5 // допуск для визначення "однакової" висоти |
| 124 | + // const horizontalDistance = Math.abs(x2 - x1) |
| 125 | + // const cornerRadius = Math.min(20, horizontalDistance / 6) // радіус заокруглення кутів |
| 126 | + // |
| 127 | + // if (Math.abs(y1 - y2) <= tolerance) { |
| 128 | + // // 1. Якщо y1 === y2 - пряма лінія |
| 129 | + // pathData = `M ${x1} ${y1} L ${x2} ${y2}` |
| 130 | + // } else { |
| 131 | + // // Точки для створення сходинки |
| 132 | + // const midX = x1 + horizontalDistance / 2 |
| 133 | + // |
| 134 | + // if (y1 < y2) { |
| 135 | + // // 2. y1 < y2 - починається прямо, потім вниз, потім прямо |
| 136 | + // pathData = `M ${x1} ${y1} |
| 137 | + // L ${midX - cornerRadius} ${y1} |
| 138 | + // Q ${midX} ${y1} ${midX} ${y1 + cornerRadius} |
| 139 | + // L ${midX} ${y2 - cornerRadius} |
| 140 | + // Q ${midX} ${y2} ${midX + cornerRadius} ${y2} |
| 141 | + // L ${x2} ${y2}` |
| 142 | + // } else { |
| 143 | + // // 3. y1 > y2 - починається прямо, потім вверх, потім прямо |
| 144 | + // pathData = `M ${x1} ${y1} |
| 145 | + // L ${midX - cornerRadius} ${y1} |
| 146 | + // Q ${midX} ${y1} ${midX} ${y1 - cornerRadius} |
| 147 | + // L ${midX} ${y2 + cornerRadius} |
| 148 | + // Q ${midX} ${y2} ${midX + cornerRadius} ${y2} |
| 149 | + // L ${x2} ${y2}` |
| 150 | + // } |
| 151 | + // } |
| 152 | + // |
| 153 | + // path.attr('d', pathData) |
| 154 | + // } |
| 155 | + |
| 156 | + // curve |
| 157 | + function updateConnection (a, b, c) { |
| 158 | + const point1 = $(a) |
| 159 | + const point2 = $(b) |
| 160 | + const parent1 = point1.parent() |
| 161 | + const parent2 = point2.parent() |
| 162 | + const svg = $(c) |
| 163 | + const path = svg.find('.cl-curve') |
| 164 | + let direction = 'horizontal' |
| 165 | + |
| 166 | + if (parent1.hasClass('east-side') && parent2.hasClass('west-side')) { |
| 167 | + direction = 'horizontal' |
| 168 | + } else if (parent1.hasClass('south-side') && parent2.hasClass('north-side')) { |
| 169 | + direction = 'vertical' |
| 170 | + } |
| 171 | + |
| 172 | + const rect1 = point1.offset() |
| 173 | + const rect2 = point2.offset() |
| 174 | + const svgRect = svg.offset() |
| 175 | + |
| 176 | + const point1Width = point1.outerWidth() |
| 177 | + const point1Height = point1.outerHeight() |
| 178 | + const point2Width = point2.outerWidth() |
| 179 | + const point2Height = point2.outerHeight() |
| 180 | + |
| 181 | + const x1 = rect1.left - svgRect.left + point1Width / 2 |
| 182 | + const y1 = rect1.top - svgRect.top + point1Height / 2 |
| 183 | + const x2 = rect2.left - svgRect.left + point2Width / 2 |
| 184 | + const y2 = rect2.top - svgRect.top + point2Height / 2 |
| 185 | + |
| 186 | + // Створюємо плавну криву для горизонтального та вертикального з'єднання |
| 187 | + const dx = x2 - x1 |
| 188 | + const dy = y2 - y1 |
| 189 | + |
| 190 | + let cp1x, cp1y, cp2x, cp2y |
| 191 | + |
| 192 | + // Визначаємо, чи з'єднання більш горизонтальне або вертикальне |
| 193 | + if (direction === 'horizontal') { |
| 194 | + // Горизонтальне з'єднання - контрольні точки по X |
| 195 | + const controlDistance = Math.abs(dx) * 0.4 |
| 196 | + cp1x = x1 + (dx > 0 ? controlDistance : -controlDistance) |
| 197 | + cp1y = y1 |
| 198 | + cp2x = x2 - (dx > 0 ? controlDistance : -controlDistance) |
| 199 | + cp2y = y2 |
| 200 | + } else { |
| 201 | + // Вертикальне з'єднання - контрольні точки по Y |
| 202 | + const controlDistance = Math.abs(dy) * 0.4 |
| 203 | + cp1x = x1 |
| 204 | + cp1y = y1 + (dy > 0 ? controlDistance : -controlDistance) |
| 205 | + cp2x = x2 |
| 206 | + cp2y = y2 - (dy > 0 ? controlDistance : -controlDistance) |
| 207 | + } |
| 208 | + |
| 209 | + // Створюємо кубічну криву Безьє |
| 210 | + const pathData = `M ${x1} ${y1} C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x2} ${y2}` |
| 211 | + |
| 212 | + path.attr('d', pathData) |
| 213 | + } |
| 214 | + |
| 215 | + function dragBlock1(){ |
| 216 | + updateConnection("#block1_a", "#block2_a", "#line-block1-block2") |
| 217 | + updateConnection("#block1_b", "#block3_a", "#line-block1-block3") |
| 218 | + } |
| 219 | + |
| 220 | + function dragBlock2(){ |
| 221 | + updateConnection("#block1_a", "#block2_a", "#line-block1-block2") |
| 222 | + } |
| 223 | + |
| 224 | + function dragBlock3(){ |
| 225 | + updateConnection("#block1_b", "#block3_a", "#line-block1-block3") |
| 226 | + } |
| 227 | + |
| 228 | + setTimeout(() => { |
| 229 | + const block1 = $('#block1') |
| 230 | + const block2 = $('#block2') |
| 231 | + const parent = $('main') |
| 232 | + |
| 233 | + block1.css({ |
| 234 | + top: parent.height() / 2 - block1.height() / 2, |
| 235 | + left: parent.width() / 2 - block1.width() / 2 - 200, |
| 236 | + }) |
| 237 | + |
| 238 | + block2.css({ |
| 239 | + top: parent.height() / 2 - block2.height() / 2, |
| 240 | + left: parent.width() / 2 - block2.width() / 2 + 200, |
| 241 | + }) |
| 242 | + |
| 243 | + updateConnection("#block1_a", "#block2_a", "#line-block1-block2") |
| 244 | + updateConnection("#block1_b", "#block3_a", "#line-block1-block3") |
| 245 | + }, 100) |
60 | 246 | </script> |
61 | 247 | </body> |
62 | 248 | </html> |
0 commit comments