From 2671f5833cf7a6d840aaefc1529461f4169a2e9a Mon Sep 17 00:00:00 2001 From: Deepak Shah Date: Thu, 7 Nov 2024 12:02:02 -0600 Subject: [PATCH] split map --- playground/nuxt.config.ts | 2 + playground/src/components/layout/SideBar.vue | 4 + .../pages/Components/s-location-search.vue | 4 +- playground/src/pages/Components/splitmap.vue | 69 ++++++ playground/src/public/compare2.svg | 4 + src/module.ts | 15 +- src/runtime/assets/scss/splitmap.scss | 121 +++++++++ src/runtime/plugins/splitmap.ts | 231 ++++++++++++++++++ src/runtime/public/icons/compare2.svg | 4 + 9 files changed, 447 insertions(+), 7 deletions(-) create mode 100644 playground/src/pages/Components/splitmap.vue create mode 100644 playground/src/public/compare2.svg create mode 100644 src/runtime/assets/scss/splitmap.scss create mode 100644 src/runtime/plugins/splitmap.ts create mode 100644 src/runtime/public/icons/compare2.svg diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index e712f19..1335d53 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -7,6 +7,8 @@ export default defineNuxtConfig({ 'vuetify-nuxt-module', '@nuxtjs/leaflet', ], + css: ['../src/runtime/assets/scss/splitmap.scss'], + devtools: { enabled: true }, compatibilityDate: '2024-08-02', imports: { diff --git a/playground/src/components/layout/SideBar.vue b/playground/src/components/layout/SideBar.vue index d6d128d..187a789 100644 --- a/playground/src/components/layout/SideBar.vue +++ b/playground/src/components/layout/SideBar.vue @@ -78,6 +78,10 @@ const components = [ title: 'SLocationSearch', link: '/components/s-location-search', }, + { + title: 'SplitMap', + link: '/components/splitmap', + }, ] diff --git a/playground/src/pages/Components/s-location-search.vue b/playground/src/pages/Components/s-location-search.vue index a4455ad..7d89c5b 100644 --- a/playground/src/pages/Components/s-location-search.vue +++ b/playground/src/pages/Components/s-location-search.vue @@ -35,7 +35,6 @@ - size string @@ -54,8 +53,7 @@ circle, and shaped. - - + lmap any diff --git a/playground/src/pages/Components/splitmap.vue b/playground/src/pages/Components/splitmap.vue new file mode 100644 index 0000000..6b7091c --- /dev/null +++ b/playground/src/pages/Components/splitmap.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/playground/src/public/compare2.svg b/playground/src/public/compare2.svg new file mode 100644 index 0000000..fde72f0 --- /dev/null +++ b/playground/src/public/compare2.svg @@ -0,0 +1,4 @@ + + compare-horizontal + + diff --git a/src/module.ts b/src/module.ts index eaa84d7..7058300 100644 --- a/src/module.ts +++ b/src/module.ts @@ -15,8 +15,18 @@ export default defineNuxtModule({ defaults: {}, setup(_options, _nuxt) { const resolver = createResolver(import.meta.url) + const runtimeDir = resolver.resolve('./runtime') + const isDevelopment = + runtimeDir.endsWith('src/runtime') || + runtimeDir.endsWith('src\\runtime') - addPlugin(resolver.resolve('./runtime/plugin')) + const styleExtension = isDevelopment ? '.scss' : '.css' + + _nuxt.options.css.push( + resolver.resolve('./runtime/assets/scss/splitmap' + styleExtension) + ) + + addPlugin(resolver.resolve('./runtime/plugins/splitmap')) addComponentsDir({ path: resolver.resolve('./runtime/components'), global: true, @@ -24,10 +34,7 @@ export default defineNuxtModule({ }) _nuxt.hook('nitro:config', (nitroConfig) => { - // Ensure `publicAssets` is an array and push the new asset directory configuration nitroConfig.publicAssets ||= [] - - // Add directory and maxAge to public assets nitroConfig.publicAssets.push({ dir: resolver.resolve('./runtime/public'), maxAge: 60 * 60 * 24 * 365, // 1 year in seconds diff --git a/src/runtime/assets/scss/splitmap.scss b/src/runtime/assets/scss/splitmap.scss new file mode 100644 index 0000000..b593d69 --- /dev/null +++ b/src/runtime/assets/scss/splitmap.scss @@ -0,0 +1,121 @@ +.leaflet-sbs-range { + position: absolute; + top: 50%; + width: 100%; + z-index: 999; +} +.leaflet-sbs-divider { + position: absolute; + top: 0; + bottom: 0; + left: 50%; + margin-left: -2px; + width: 4px; + background-color: rgb(var(--v-theme-primary)); + pointer-events: none; + z-index: 999; +} +.leaflet-sbs-range { + appearance: none; + display: inline-block !important; + vertical-align: middle; + height: 0; + padding: 0; + margin: 0; + border: 0; + background: rgba(0, 0, 0, 0.25); + min-width: 100px; + cursor: pointer; + pointer-events: none; + z-index: 999; +} +.leaflet-sbs-range::-ms-fill-upper { + background: transparent; +} +.leaflet-sbs-range::-ms-fill-lower { + background: rgba(255, 255, 255, 0.25); +} +/* Browser thingies */ + +.leaflet-sbs-range::-moz-range-track { + opacity: 0; +} +.leaflet-sbs-range::-ms-track { + opacity: 0; +} +.leaflet-sbs-range::-ms-tooltip { + display: none; +} +/* For whatever reason, these need to be defined + * on their own so dont group them */ + +.leaflet-sbs-range::-webkit-slider-thumb { + -webkit-appearance: none; + margin: 0; + padding: 0; + background: rgb(var(--v-theme-primary)); + height: 40px; + width: 40px; + border-radius: 20px; + cursor: ew-resize; + pointer-events: auto; + border: 1px solid rgb(var(--v-theme-primary)); + background-image: url('/icons/compare2.svg'); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 40px 40px; + filter: brightness(0) saturate(100%) rgb(var(--v-theme-primary)); +} + +.leaflet-sbs-range::-ms-thumb { + margin: 0; + padding: 0; + background: rgb(var(--v-theme-primary)); + height: 40px; + width: 40px; + border-radius: 20px; + cursor: ew-resize; + pointer-events: auto; + border: 1px solid rgb(var(--v-theme-primary)); + background-image: url('/icons/compare2.svg'); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 40px 40px; + filter: brightness(0) saturate(100%) rgb(var(--v-theme-primary)); +} + +.leaflet-sbs-range::-moz-range-thumb { + padding: 0; + right: 0; + background: rgb(var(--v-theme-primary)); + height: 40px; + width: 40px; + border-radius: 20px; + cursor: ew-resize; + pointer-events: auto; + border: 1px solid rgb(var(--v-theme-primary)); + background-image: url('/icons/compare2.svg'); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 40px 40px; + filter: brightness(0) saturate(100%) rgb(var(--v-theme-primary)); +} + +.leaflet-sbs-range:disabled::-moz-range-thumb { + cursor: default; +} +.leaflet-sbs-range:disabled::-ms-thumb { + cursor: default; +} +.leaflet-sbs-range:disabled::-webkit-slider-thumb { + cursor: default; +} +.leaflet-sbs-range:disabled { + cursor: default; +} +.leaflet-sbs-range:focus { + outline: none !important; +} +.leaflet-sbs-range::-moz-focus-outer { + border: 0; +} \ No newline at end of file diff --git a/src/runtime/plugins/splitmap.ts b/src/runtime/plugins/splitmap.ts new file mode 100644 index 0000000..1c2a4e8 --- /dev/null +++ b/src/runtime/plugins/splitmap.ts @@ -0,0 +1,231 @@ +import L from 'leaflet' + +// Your provided SplitMap control code here... +let mapWasDragEnabled +let mapWasTapEnabled + +function on(el, types, fn, context) { + types.split(' ').forEach(function (type) { + L.DomEvent.on(el, type, fn, context) + }) +} + +function off(el, types, fn, context) { + types.split(' ').forEach(function (type) { + L.DomEvent.off(el, type, fn, context) + }) +} + +function getRangeEvent(rangeInput) { + return 'oninput' in rangeInput ? 'input' : 'change' +} + +function cancelMapDrag() { + mapWasDragEnabled = this._map.dragging.enabled() + mapWasTapEnabled = this._map.tap && this._map.tap.enabled() + this._map.dragging.disable() + this._map.tap && this._map.tap.disable() +} + +function uncancelMapDrag(e) { + this._refocusOnMap(e) + if (mapWasDragEnabled) { + this._map.dragging.enable() + } + if (mapWasTapEnabled) { + this._map.tap.enable() + } +} + +function asArray(arg) { + return arg === undefined ? [] : Array.isArray(arg) ? arg : [arg] +} + +function noop() { + return +} + +L.Control.SplitMap = L.Control.extend({ + options: { + thumbSize: 42, + padding: 0, + }, + + initialize: function (leftLayers, rightLayers, options) { + this._leftLayers = asArray(leftLayers) + this._rightLayers = asArray(rightLayers) + L.setOptions(this, options) + }, + + getPosition: function () { + const rangeValue = this._range.value + const offset = + (0.5 - rangeValue) * + (2 * this.options.padding + this.options.thumbSize) + return this._map.getSize().x * rangeValue + offset + }, + + setPosition: noop, + + includes: + L.version.split('.')[0] === '1' ? L.Evented.prototype : L.Mixin.Events, + + addTo: function (map) { + this.remove() + this._map = map + const container = (this._container = L.DomUtil.create( + 'div', + 'leaflet-sbs', + map._controlContainer + )) + this._divider = L.DomUtil.create( + 'div', + 'leaflet-sbs-divider', + container + ) + const range = (this._range = L.DomUtil.create( + 'input', + 'leaflet-sbs-range', + container + )) + range.type = 'range' + range.min = 0 + range.max = 1 + range.step = 'any' + range.value = 0.5 + range.style.paddingLeft = range.style.paddingRight = + this.options.padding + 'px' + this._addEvents() + this._updateClip() + return this + }, + + remove: function () { + if (!this._map) { + return this + } + this._clearClipping() + this._removeEvents() + L.DomUtil.remove(this._container) + this._map = null + return this + }, + + _clearClipping: function () { + this._leftLayers.forEach((left_layer) => { + if (left_layer.getContainer) { + left_layer.getContainer().style.clip = '' + } else { + left_layer.getPane().style.clip = '' + } + }) + + this._rightLayers.forEach((right_layer) => { + if (right_layer.getContainer) { + right_layer.getContainer().style.clip = '' + } else { + right_layer.getPane().style.clip = '' + } + }) + }, + + _updateClip: function () { + if (!this._map) { + return this + } + const map = this._map + const nw = map.containerPointToLayerPoint([0, 0]) + const se = map.containerPointToLayerPoint(map.getSize()) + const clipX = nw.x + this.getPosition() + const dividerX = this.getPosition() + this._divider.style.left = dividerX + 'px' + this.fire('dividermove', { x: dividerX }) + const clipLeft = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)' + const clipRight = + 'rect(' + [nw.y, se.x, se.y, clipX].join('px,') + 'px)' + + this._leftLayers.forEach((left_layer) => { + if (left_layer.getContainer) { + left_layer.getContainer().style.clip = clipLeft + } else { + left_layer.getPane().style.clip = clipLeft + } + }) + + this._rightLayers.forEach((right_layer) => { + if (right_layer.getContainer) { + right_layer.getContainer().style.clip = clipRight + } else { + right_layer.getPane().style.clip = clipRight + } + }) + }, + + _addEvents: function () { + const range = this._range + const map = this._map + if (!map || !range) return + map.on('move', this._updateClip, this) + map.on('layeradd layerremove', this._updateLayers, this) + on(range, getRangeEvent(range), this._updateClip, this) + on( + range, + 'ontouchstart' in window ? 'touchstart' : 'mousedown', + cancelMapDrag, + this + ) + on( + range, + 'ontouchend' in window ? 'touchend' : 'mouseup', + uncancelMapDrag, + this + ) + }, + + _removeEvents: function () { + const range = this._range + const map = this._map + if (range) { + off(range, getRangeEvent(range), this._updateClip, this) + off( + range, + 'ontouchstart' in window ? 'touchstart' : 'mousedown', + cancelMapDrag, + this + ) + off( + range, + 'ontouchend' in window ? 'touchend' : 'mouseup', + uncancelMapDrag, + this + ) + } + if (map) { + map.off('layeradd layerremove', this._updateLayers, this) + map.off('move', this._updateClip, this) + } + }, + + _updateLayers: function () { + this._updateClip() + }, + + setLeftLayers: function (layers) { + this._leftLayers = asArray(layers) + this._updateLayers() + }, + + setRightLayers: function (layers) { + this._rightLayers = asArray(layers) + this._updateLayers() + }, +}) + +L.control.splitMap = function (leftLayers, rightLayers, options) { + return new L.Control.SplitMap(leftLayers, rightLayers, options) +} + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.provide('SplitMap', L.control.splitMap) + // nuxtApp.provide('SplitMap', ()=>{console.log("hello world",L.control.splitMap ,L.Control.SplitMap )}) +}) diff --git a/src/runtime/public/icons/compare2.svg b/src/runtime/public/icons/compare2.svg new file mode 100644 index 0000000..fde72f0 --- /dev/null +++ b/src/runtime/public/icons/compare2.svg @@ -0,0 +1,4 @@ + + compare-horizontal + +