diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-21 14:49:37 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-21 17:08:05 +0800 |
| commit | e015aeb2c13903871da306d3aa840c25c7a3597f (patch) | |
| tree | 96d321d06d517ccb23879d3b58ac901a1f3fb270 /src | |
| parent | bdf723a126a0d435233c1b4a1e3c00110bc9ea94 (diff) | |
feat: add font-size plus/minus button
* When draggable handle is on hover, they appears
* Hide when drag start, show when drag end
Diffstat (limited to 'src')
| -rw-r--r-- | src/OverlayLayout.mjs | 33 | ||||
| -rw-r--r-- | src/css/dumbymap.css | 80 |
2 files changed, 92 insertions, 21 deletions
diff --git a/src/OverlayLayout.mjs b/src/OverlayLayout.mjs index c87033b..8b4e073 100644 --- a/src/OverlayLayout.mjs +++ b/src/OverlayLayout.mjs | |||
| @@ -10,11 +10,18 @@ export class OverlayLayout { | |||
| 10 | // Create draggable block | 10 | // Create draggable block |
| 11 | const draggableBlock = document.createElement('div') | 11 | const draggableBlock = document.createElement('div') |
| 12 | draggableBlock.classList.add('draggable-block') | 12 | draggableBlock.classList.add('draggable-block') |
| 13 | draggableBlock.innerHTML = ` | ||
| 14 | <div class="draggable"> | ||
| 15 | <div class="handle">\u2630</div> | ||
| 16 | </div> | ||
| 17 | <div class="utils"> | ||
| 18 | <div id="plus-font-size" ">\u2795</div> | ||
| 19 | <div id="minus-font-size">\u2796</div> | ||
| 20 | </div> | ||
| 21 | ` | ||
| 13 | 22 | ||
| 14 | // Add draggable part | 23 | // Add draggable part |
| 15 | const draggablePart = document.createElement('div'); | 24 | const draggablePart = draggableBlock.querySelector('.draggable') |
| 16 | draggablePart.classList.add('draggable') | ||
| 17 | draggablePart.textContent = '☰' | ||
| 18 | draggablePart.title = 'Use middle-click to remove block' | 25 | draggablePart.title = 'Use middle-click to remove block' |
| 19 | draggablePart.onmouseup = (e) => { | 26 | draggablePart.onmouseup = (e) => { |
| 20 | if (e.button === 1) { | 27 | if (e.button === 1) { |
| @@ -34,6 +41,26 @@ export class OverlayLayout { | |||
| 34 | snap: { x: { step: 20 }, y: { step: 20 } }, | 41 | snap: { x: { step: 20 }, y: { step: 20 } }, |
| 35 | }) | 42 | }) |
| 36 | 43 | ||
| 44 | // Plus/Minus font-size of content | ||
| 45 | const plusButton = draggableBlock.querySelector('#plus-font-size') | ||
| 46 | plusButton.onclick = () => { | ||
| 47 | const fontSize = parseFloat(getComputedStyle(block).fontSize) / 16 | ||
| 48 | block.style.fontSize = `${fontSize + 0.1}rem` | ||
| 49 | } | ||
| 50 | const minusButton = draggableBlock.querySelector('#minus-font-size') | ||
| 51 | minusButton.onclick = () => { | ||
| 52 | const fontSize = parseFloat(getComputedStyle(block).fontSize) / 16 | ||
| 53 | block.style.fontSize = `${fontSize - 0.1}rem` | ||
| 54 | } | ||
| 55 | draggableInstance.onDragStart = () => { | ||
| 56 | plusButton.style.opacity = '0' | ||
| 57 | minusButton.style.opacity = '0' | ||
| 58 | } | ||
| 59 | draggableInstance.onDragEnd = () => { | ||
| 60 | plusButton.style = '' | ||
| 61 | minusButton.style = '' | ||
| 62 | } | ||
| 63 | |||
| 37 | // Reposition draggable instance when resized | 64 | // Reposition draggable instance when resized |
| 38 | new ResizeObserver(() => { | 65 | new ResizeObserver(() => { |
| 39 | try { | 66 | try { |
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 84da02f..f5695f1 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
| @@ -85,7 +85,7 @@ | |||
| 85 | padding: 0; | 85 | padding: 0; |
| 86 | 86 | ||
| 87 | position: relative; | 87 | position: relative; |
| 88 | overflow-x: scroll; | 88 | overflow-x: auto; |
| 89 | max-width: 60em; | 89 | max-width: 60em; |
| 90 | 90 | ||
| 91 | /* height: 100vh; */ | 91 | /* height: 100vh; */ |
| @@ -114,7 +114,7 @@ | |||
| 114 | .SemanticHtml { | 114 | .SemanticHtml { |
| 115 | width: 100%; | 115 | width: 100%; |
| 116 | padding: 1.5rem; | 116 | padding: 1.5rem; |
| 117 | overflow-y: scroll; | 117 | overflow-y: auto; |
| 118 | order: 1; | 118 | order: 1; |
| 119 | 119 | ||
| 120 | pre { | 120 | pre { |
| @@ -167,7 +167,7 @@ | |||
| 167 | .DumbyMap[data-layout="side"] { | 167 | .DumbyMap[data-layout="side"] { |
| 168 | .SemanticHtml { | 168 | .SemanticHtml { |
| 169 | flex: 50%; | 169 | flex: 50%; |
| 170 | overflow-y: scroll; | 170 | overflow-y: auto; |
| 171 | 171 | ||
| 172 | height: 100vh; | 172 | height: 100vh; |
| 173 | } | 173 | } |
| @@ -190,7 +190,7 @@ | |||
| 190 | margin: 0; | 190 | margin: 0; |
| 191 | padding: 0; | 191 | padding: 0; |
| 192 | 192 | ||
| 193 | position: absolute; | 193 | position: fixed; |
| 194 | top: 0; | 194 | top: 0; |
| 195 | left: 0; | 195 | left: 0; |
| 196 | } | 196 | } |
| @@ -207,22 +207,21 @@ | |||
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | .draggable-block { | 209 | .draggable-block { |
| 210 | overflow: clip; | 210 | overflow: visible; |
| 211 | box-sizing: content-box; | ||
| 212 | width: fit-content; | 211 | width: fit-content; |
| 213 | 212 | ||
| 214 | position: absolute; | 213 | position: absolute; |
| 215 | 214 | ||
| 216 | border: solid gray; | 215 | border: solid gray 3px; |
| 217 | border-radius: 0.5rem; | 216 | border-radius: 0.5rem; |
| 218 | 217 | ||
| 219 | background-color: white; | 218 | background-color: white; |
| 220 | 219 | ||
| 221 | font-size: 12px; | 220 | font-size: 0.8rem; |
| 222 | pointer-events: auto; | 221 | pointer-events: auto; |
| 223 | 222 | ||
| 224 | .dumby-block { | 223 | .dumby-block { |
| 225 | overflow: scroll; | 224 | overflow: auto; |
| 226 | margin: 0; | 225 | margin: 0; |
| 227 | 226 | ||
| 228 | position: relative; | 227 | position: relative; |
| @@ -264,31 +263,76 @@ | |||
| 264 | 263 | ||
| 265 | .draggable { | 264 | .draggable { |
| 266 | display: block; | 265 | display: block; |
| 266 | overflow: clip; | ||
| 267 | width: 100%; | 267 | width: 100%; |
| 268 | 268 | ||
| 269 | position: absolute; | 269 | position: absolute; |
| 270 | top: 0; | 270 | top: 0; |
| 271 | left: 0; | 271 | left: 0; |
| 272 | z-index: 1; | 272 | z-index: 1; |
| 273 | outline: red 3px; | ||
| 274 | border-top-left-radius: 0.3rem; | ||
| 275 | border-top-right-radius: 0.3rem; | ||
| 276 | |||
| 277 | .handle { | ||
| 278 | font-size: 1.1rem; | ||
| 279 | text-align: center; | ||
| 280 | |||
| 281 | transition: all 0.3s ease-in-out; | ||
| 282 | transform: translate(0, -0.6rem); | ||
| 283 | } | ||
| 284 | } | ||
| 273 | 285 | ||
| 274 | font-size: 1.1rem; | 286 | .utils { |
| 275 | text-align: center; | 287 | display: none; |
| 288 | } | ||
| 276 | 289 | ||
| 277 | transition: all 0.3s ease-in-out; | 290 | &:has(.draggable:hover, .utils:hover) { |
| 278 | transform: translate(0, -0.6rem); | 291 | .dumby-block { |
| 292 | color: gray; | ||
| 279 | 293 | ||
| 280 | &:hover { | 294 | opacity: 0.7; |
| 295 | } | ||
| 296 | |||
| 297 | .handle { | ||
| 281 | background: #e1e1e1; | 298 | background: #e1e1e1; |
| 282 | 299 | ||
| 283 | border-bottom: solid gray; | 300 | /* border-bottom: solid gray; */ |
| 284 | 301 | ||
| 285 | transform: unset; | 302 | transform: unset; |
| 303 | } | ||
| 286 | 304 | ||
| 287 | & ~ * { | 305 | .utils { |
| 288 | color: gray; | 306 | display: flex; |
| 289 | 307 | ||
| 290 | opacity: 0.7; | 308 | position: absolute; |
| 309 | top: 0; | ||
| 310 | top: -0.5rem; | ||
| 311 | left: 100%; | ||
| 312 | |||
| 313 | font-size: 1.5rem; | ||
| 314 | gap: 6px; | ||
| 315 | animation: fade-in 1.5s; | ||
| 316 | padding-left: 1rem; | ||
| 317 | |||
| 318 | [id$="-font-size"]{ | ||
| 319 | padding: 0.2rem 0.4rem; | ||
| 320 | |||
| 321 | border: 3px gray solid; | ||
| 322 | border-radius: 5px; | ||
| 323 | |||
| 324 | background: white; | ||
| 325 | |||
| 326 | transition: all 1s ease-in-out; | ||
| 291 | } | 327 | } |
| 328 | |||
| 329 | #plus-font-size { | ||
| 330 | cursor: zoom-in; | ||
| 331 | } | ||
| 332 | |||
| 333 | #minus-font-size { | ||
| 334 | cursor: zoom-out; | ||
| 335 | } | ||
| 292 | } | 336 | } |
| 293 | } | 337 | } |
| 294 | } | 338 | } |