diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-15 00:16:02 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-15 11:02:28 +0800 |
| commit | e25db413c595623b18315bd716ba7171f32ccc51 (patch) | |
| tree | 867066377fc73dd802eb3f2bff78d5bc86d4f431 /src | |
| parent | 8aadc8fd3b69fbd8a030e88426816c38ca32f4af (diff) | |
feat: Improve draggable behavior in overlay layout
* Set position=absolute on each block, so they won't affect each others'
y value when display=none (about Block Formatting Context)
* Add title tooltip for removing block
* Simple logic to set initial position of block by their width
Diffstat (limited to 'src')
| -rw-r--r-- | src/css/dumbymap.css | 1 | ||||
| -rw-r--r-- | src/dumbymap.mjs | 60 |
2 files changed, 40 insertions, 21 deletions
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 1dc7a09..8e28af5 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
| @@ -142,6 +142,7 @@ | |||
| 142 | 142 | ||
| 143 | > .draggable-block { | 143 | > .draggable-block { |
| 144 | box-sizing: content-box; | 144 | box-sizing: content-box; |
| 145 | position: absolute; | ||
| 145 | width: fit-content; | 146 | width: fit-content; |
| 146 | max-height: 50vh; | 147 | max-height: 50vh; |
| 147 | overflow: scroll; | 148 | overflow: scroll; |
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index f9a999b..4d4628d 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
| @@ -294,6 +294,26 @@ export const generateMaps = async (container) => { | |||
| 294 | console.info(renderInfo) | 294 | console.info(renderInfo) |
| 295 | 295 | ||
| 296 | //}}} | 296 | //}}} |
| 297 | // Draggable Blocks{{{ | ||
| 298 | // Add draggable part for blocks | ||
| 299 | htmlHolder.blocks = Array.from(htmlHolder.querySelectorAll('.draggable-block')) | ||
| 300 | htmlHolder.blocks.forEach(block => { | ||
| 301 | // Add draggable part | ||
| 302 | const draggablePart = document.createElement('div'); | ||
| 303 | draggablePart.classList.add('draggable') | ||
| 304 | draggablePart.textContent = '☰' | ||
| 305 | draggablePart.title = 'Use middle-click to remove block' | ||
| 306 | block.insertBefore(draggablePart, block.firstChild) | ||
| 307 | block.draggablePart = draggablePart | ||
| 308 | |||
| 309 | draggablePart.onmouseup = (e) => { | ||
| 310 | if (e.button === 1) { | ||
| 311 | block.style.display = "none"; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | }) | ||
| 315 | |||
| 316 | // }}} | ||
| 297 | // CSS observer {{{ | 317 | // CSS observer {{{ |
| 298 | 318 | ||
| 299 | // Set focusArea | 319 | // Set focusArea |
| @@ -323,20 +343,6 @@ export const generateMaps = async (container) => { | |||
| 323 | } | 343 | } |
| 324 | } | 344 | } |
| 325 | 345 | ||
| 326 | // Add draggable part for blocks | ||
| 327 | htmlHolder.blocks = Array.from(htmlHolder.querySelectorAll('.draggable-block')) | ||
| 328 | htmlHolder.blocks.forEach(block => { | ||
| 329 | const draggablePart = document.createElement('div'); | ||
| 330 | draggablePart.classList.add('draggable') | ||
| 331 | draggablePart.textContent = '☰' | ||
| 332 | |||
| 333 | // TODO Better way to close block | ||
| 334 | draggablePart.onmouseup = (e) => { | ||
| 335 | if (e.button === 1) block.style.display = "none"; | ||
| 336 | } | ||
| 337 | block.insertBefore(draggablePart, block.firstChild) | ||
| 338 | }) | ||
| 339 | |||
| 340 | // observe layout change | 346 | // observe layout change |
| 341 | const layoutObserver = new MutationObserver(() => { | 347 | const layoutObserver = new MutationObserver(() => { |
| 342 | const layout = container.getAttribute('data-layout') | 348 | const layout = container.getAttribute('data-layout') |
| @@ -363,17 +369,29 @@ export const generateMaps = async (container) => { | |||
| 363 | } | 369 | } |
| 364 | 370 | ||
| 365 | if (layout === 'overlay') { | 371 | if (layout === 'overlay') { |
| 366 | htmlHolder.blocks.forEach(block => { | 372 | let x = 0; |
| 367 | block.draggableInstance = new PlainDraggable(block, { handle: block.querySelector('.draggable') }) | 373 | let y = 0; |
| 368 | block.draggableInstance.snap = { x: { step: 20 }, y: { step: 20 } } | 374 | htmlHolder.blocks.forEach(block =>{ |
| 369 | // block.draggableInstance.onDragEnd = () => { | 375 | block.draggableInstance = new PlainDraggable(block, { |
| 370 | // links(block).forEach(link => link.line.position()) | 376 | handle: block.draggablePart, |
| 371 | // } | 377 | snap: { x: { step: 20 }, y: { step: 20 } }, |
| 378 | autoScroll: false, | ||
| 379 | }) | ||
| 380 | // block.style.transform = `translate(${x}px, ${y}px)` | ||
| 381 | block.style.left = `${x}px` | ||
| 382 | block.style.top = `${y}px` | ||
| 383 | x += parseInt(window.getComputedStyle(block).width) + 50 | ||
| 384 | if (x > window.innerWidth) { | ||
| 385 | y += 200 | ||
| 386 | x = x % window.innerWidth | ||
| 387 | } | ||
| 372 | }) | 388 | }) |
| 373 | } else { | 389 | } else { |
| 374 | htmlHolder.blocks.forEach(block => { | 390 | htmlHolder.blocks.forEach(block => { |
| 375 | block.style.transform = 'none' | 391 | block.style.transform = 'none' |
| 376 | block.draggableInstance?.remove() | 392 | try { |
| 393 | block.draggableInstance?.remove() | ||
| 394 | } catch (err) { } | ||
| 377 | }) | 395 | }) |
| 378 | } | 396 | } |
| 379 | }); | 397 | }); |