From f6b2421937b37173b3c732ca7834fc14053e895f Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Sun, 22 Sep 2024 00:40:06 +0800 Subject: feat: add resize bar for side-by-side layout * SVG comes from maplibre-gl-compare * plain-draggable is awesome! --- src/Layout.mjs | 43 ++++++++++++++++++++++- src/css/dumbymap.css | 99 ++++++++++++++++++++++++++++++++++++++-------------- src/dumbymap.mjs | 9 ++--- 3 files changed, 119 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/Layout.mjs b/src/Layout.mjs index 861f56b..5673722 100644 --- a/src/Layout.mjs +++ b/src/Layout.mjs @@ -11,7 +11,48 @@ export class Layout { valueOf = () => this.name } -export class OverlayLayout extends Layout { +export class SideBySide extends Layout { + name = "side-by-side" + + enterHandler = ({ container, htmlHolder, showcase }) => { + const bar = document.createElement('div') + bar.className = 'bar' + bar.innerHTML = '
' + const handle = bar.querySelector('.bar-handle') + container.appendChild(bar) + + const resizeByLeft = (left) => { + htmlHolder.style.width = (left) + "px" + showcase.style.width = (parseFloat(getComputedStyle(container).width) - left) + "px" + } + + const draggable = new PlainDraggable(bar, { + handle: handle, + containment: { left: '25%', top: 0, right: '75%', height: 0 }, + }) + draggable.draggableCursor = "grab" + draggable.onDrag = (pos) => { + handle.style.transform = 'unset' + resizeByLeft(pos.left) + } + draggable.onDragEnd = (_) => { + handle.removeAttribute('style') + } + + new ResizeObserver(() => { + if (draggable) resizeByLeft(draggable.left) + }).observe(container); + } + + leaveHandler = ({ container, htmlHolder, showcase }) => { + container.removeAttribute('style') + htmlHolder.removeAttribute('style') + showcase.removeAttribute('style') + container.querySelector('.bar')?.remove() + } +} + +export class Overlay extends Layout { name = "overlay" enterHandler = (dumbymap) => { diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 68a73c0..f58cf22 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css @@ -80,7 +80,6 @@ } .DumbyMap { - display: flex; width: 100%; height: 100%; margin: 0 auto; @@ -89,32 +88,10 @@ position: relative; overflow-x: auto; - .Showcase { - display: none; - overflow: visible; - - position: relative; - order: 2; - - > * { - width: 100%; - height: 100%; - - position: absolute; - top: 0; - left: 0; - } - - [data-focus="true"] { - z-index: 1; - } - } - .SemanticHtml { - width: 100%; + height: 100%; padding: 1.5rem; overflow-y: auto; - order: 1; pre { width: 100%; @@ -149,6 +126,28 @@ animation: fade-out 1s; } } + + .Showcase { + display: none; + overflow: visible; + height: 100%; + + position: relative; + + > * { + width: 100%; + height: 100%; + + position: absolute; + top: 0; + left: 0; + } + + [data-focus="true"] { + z-index: 1; + } + } + } .DumbyMap[data-layout="normal"] { @@ -156,14 +155,60 @@ } .DumbyMap[data-layout="side-by-side"] { - display: flex; - .SemanticHtml, .Showcase { - flex: 50%; + width: 50%; + position: absolute; + top: 0; + min-width: 20%; + } + + .SemanticHtml { + left: 0; + } + + .Showcase { display: block; + + right: 0; + } + + .bar { + display: flex; + overflow: visible; + width: 1px; height: 100%; + + position: absolute; + left: 50%; + z-index: 9999; + + border: 2px black solid; + + .bar-handle { + display: inline-block; + width: 60px; + height: 60px; + + position: absolute; + top: calc(50% - 30px); + left: -30px; + + border-radius: 50%; + + background-color: #3887be; + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgd2lkdGg9IjYwIiAgIGhlaWdodD0iNjAiICAgdmVyc2lvbj0iMS4xIiAgIHZpZXdCb3g9IjAgMCA2MCA2MCIgICBpZD0ic3ZnNTQzNCIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkxK2RldmVsK29zeG1lbnUgcjEyOTExIiAgIHNvZGlwb2RpOmRvY25hbWU9Imwtci5zdmciPiAgPG1ldGFkYXRhICAgICBpZD0ibWV0YWRhdGE1NDQ0Ij4gICAgPHJkZjpSREY+ICAgICAgPGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+ICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4gICAgICAgIDxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+ICAgICAgPC9jYzpXb3JrPiAgICA8L3JkZjpSREY+ICA8L21ldGFkYXRhPiAgPGRlZnMgICAgIGlkPSJkZWZzNTQ0MiIgLz4gIDxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTI4NiIgICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijc1MSIgICAgIGlkPSJuYW1lZHZpZXc1NDQwIiAgICAgc2hvd2dyaWQ9InRydWUiICAgICBpbmtzY2FwZTp6b29tPSI0IiAgICAgaW5rc2NhcGU6Y3g9IjI1Ljg4OTgzMSIgICAgIGlua3NjYXBlOmN5PSIzNC4zODE4MzMiICAgICBpbmtzY2FwZTp3aW5kb3cteD0iMCIgICAgIGlua3NjYXBlOndpbmRvdy15PSIyMyIgICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmc1NDM0IiAgICAgaW5rc2NhcGU6b2JqZWN0LW5vZGVzPSJ0cnVlIiAgICAgaW5rc2NhcGU6c25hcC1zbW9vdGgtbm9kZXM9InRydWUiPiAgICA8aW5rc2NhcGU6Z3JpZCAgICAgICB0eXBlPSJ4eWdyaWQiICAgICAgIGlkPSJncmlkNTk4OSIgLz4gIDwvc29kaXBvZGk6bmFtZWR2aWV3PiAgPHBhdGggICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjFweDtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIiAgICAgZD0iTSAyNSAyNCBMIDE2IDMwIEwgMjUgMzYgTCAyNSAyNCB6IE0gMzUgMjQgTCAzNSAzNiBMIDQ0IDMwIEwgMzUgMjQgeiAiICAgICBpZD0icGF0aDU5OTUiIC8+PC9zdmc+"); + + transition: transform 0.3s ease-in-out; + transform: scale(0.5, 0.5); + box-shadow: inset 0 0 0 2px white; + + &:hover { + transform: unset; + } + } + } } diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index a785d6f..87ea694 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -6,15 +6,15 @@ import MarkdownItTocDoneRight from 'markdown-it-toc-done-right' import LeaderLine from 'leader-line' import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay' import { onRemove, animateRectTransition, throttle } from './utils' -import { Layout, OverlayLayout } from './Layout' +import { Layout, SideBySide, Overlay } from './Layout' const docLinkSelector = 'a[href^="#"][title^="=>"]' const geoLinkSelector = 'a[href^="geo:"]' const layouts = [ new Layout({ name: "normal" }), - new Layout({ name: "side-by-side" }), - new OverlayLayout({ name: "overlay" }), + new SideBySide({ name: "side-by-side" }), + new Overlay({ name: "overlay" }), ] // FUNCTION: Get DocLinks from special anchor element {{{ @@ -144,9 +144,10 @@ export const generateMaps = async (container, callback) => { showcase.classList.add('Showcase') const dumbymap = { - blocks: Array.from(htmlHolder.querySelectorAll('.dumby-block')), + container: container, htmlHolder: htmlHolder, showcase: showcase, + blocks: Array.from(htmlHolder.querySelectorAll('.dumby-block')), } container.classList.add('DumbyMap') -- cgit v1.2.3-70-g09d2