diff --git a/docs/examples/deckgl_layer/app.py b/docs/examples/deckgl_layer/app.py index f67a32dd..3ffe81d9 100644 --- a/docs/examples/deckgl_layer/app.py +++ b/docs/examples/deckgl_layer/app.py @@ -1,8 +1,12 @@ # Shiny Express App +import json + from maplibre import Map, MapOptions, render_maplibregl from maplibre.basemaps import Carto from maplibre.ui import use_deckgl + +# from shiny import reactive from shiny.express import input, render, ui m = Map( @@ -15,8 +19,10 @@ ) ) +layer_id = "GridLayer" + deck_grid_layer = { - "@@type": "GridLayer", + "@@type": layer_id, "id": "GridLayer", "data": "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf-bike-parking.json", "extruded": True, @@ -39,6 +45,17 @@ def render_map(): return m +# @reactive.Effect +# @reactive.event(input.render_map_layer_GridLayer) +@render.code +def picking_object(): + obj = input.render_map_layer_GridLayer() + print(obj) + # return json.dumps(obj, indent=2) if obj else "Pick a feature!" + # return f"{obj['count']}" if obj else "Pick a feature!" + return json.dumps(obj["points"], indent=2) if obj else "Pick a feature!" + + if __name__ == "__main__": with open("docs/examples/deckgl_layer/app.html", "w") as f: f.write(m.to_html()) diff --git a/maplibre/srcjs/index.js b/maplibre/srcjs/index.js index 6c359ae2..5187b874 100644 --- a/maplibre/srcjs/index.js +++ b/maplibre/srcjs/index.js @@ -1,7 +1,7 @@ -(()=>{var D=Object.prototype.toString,S=Array.isArray||function(e){return D.call(e)==="[object Array]"};function P(r){return typeof r=="function"}function A(r){return S(r)?"array":typeof r}function L(r){return r.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function j(r,e){return r!=null&&typeof r=="object"&&e in r}function B(r,e){return r!=null&&typeof r!="object"&&r.hasOwnProperty&&r.hasOwnProperty(e)}var H=RegExp.prototype.test;function J(r,e){return H.call(r,e)}var F=/\S/;function W(r){return!J(F,r)}var q={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function G(r){return String(r).replace(/[&<>"'`=\/]/g,function(t){return q[t]})}var K=/\s*/,V=/\s+/,U=/\s*=/,z=/\s*\}/,Q=/#|\^|\/|>|\{|&|=|!/;function X(r,e){if(!r)return[];var t=!1,n=[],a=[],s=[],o=!1,i=!1,p="",u=0;function f(){if(o&&!i)for(;s.length;)delete a[s.pop()];else s=[];o=!1,i=!1}var v,m,x;function N(y){if(typeof y=="string"&&(y=y.split(V,2)),!S(y)||y.length!==2)throw new Error("Invalid tags: "+y);v=new RegExp(L(y[0])+"\\s*"),m=new RegExp("\\s*"+L(y[1])),x=new RegExp("\\s*"+L("}"+y[1]))}N(e||g.tags);for(var l=new T(r),w,h,d,k,M,b;!l.eos();){if(w=l.pos,d=l.scanUntil(v),d)for(var E=0,$=d.length;E<$;++E)k=d.charAt(E),W(k)?(s.push(a.length),p+=k):(i=!0,t=!0,p+=" "),a.push(["text",k,w,w+1]),w+=1,k===` -`&&(f(),p="",u=0,t=!1);if(!l.scan(v))break;if(o=!0,h=l.scan(Q)||"name",l.scan(K),h==="="?(d=l.scanUntil(U),l.scan(U),l.scanUntil(m)):h==="{"?(d=l.scanUntil(x),l.scan(z),l.scanUntil(m),h="&"):d=l.scanUntil(m),!l.scan(m))throw new Error("Unclosed tag at "+l.pos);if(h==">"?M=[h,d,w,l.pos,p,u,t]:M=[h,d,w,l.pos],u++,a.push(M),h==="#"||h==="^")n.push(M);else if(h==="/"){if(b=n.pop(),!b)throw new Error('Unopened section "'+d+'" at '+w);if(b[1]!==d)throw new Error('Unclosed section "'+b[1]+'" at '+w)}else h==="name"||h==="{"||h==="&"?i=!0:h==="="&&N(d)}if(f(),b=n.pop(),b)throw new Error('Unclosed section "'+b[1]+'" at '+l.pos);return Z(Y(a))}function Y(r){for(var e=[],t,n,a=0,s=r.length;a0?n[n.length-1][4]:e;break;default:t.push(a)}return e}function T(r){this.string=r,this.tail=r,this.pos=0}T.prototype.eos=function(){return this.tail===""};T.prototype.scan=function(e){var t=this.tail.match(e);if(!t||t.index!==0)return"";var n=t[0];return this.tail=this.tail.substring(n.length),this.pos+=n.length,n};T.prototype.scanUntil=function(e){var t=this.tail.search(e),n;switch(t){case-1:n=this.tail,this.tail="";break;case 0:n="";break;default:n=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=n.length,n};function C(r,e){this.view=r,this.cache={".":this.view},this.parent=e}C.prototype.push=function(e){return new C(e,this)};C.prototype.lookup=function(e){var t=this.cache,n;if(t.hasOwnProperty(e))n=t[e];else{for(var a=this,s,o,i,p=!1;a;){if(e.indexOf(".")>0)for(s=a.view,o=e.split("."),i=0;s!=null&&i"?u=this.renderPartial(i,t,n,s):p==="&"?u=this.unescapedValue(i,t):p==="name"?u=this.escapedValue(i,t,s):p==="text"&&(u=this.rawValue(i)),u!==void 0&&(o+=u);return o};c.prototype.renderSection=function(e,t,n,a,s){var o=this,i="",p=t.lookup(e[1]);function u(m){return o.render(m,t,n,s)}if(p){if(S(p))for(var f=0,v=p.length;f{var D=Object.prototype.toString,_=Array.isArray||function(e){return D.call(e)==="[object Array]"};function P(r){return typeof r=="function"}function A(r){return _(r)?"array":typeof r}function L(r){return r.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function I(r,e){return r!=null&&typeof r=="object"&&e in r}function B(r,e){return r!=null&&typeof r!="object"&&r.hasOwnProperty&&r.hasOwnProperty(e)}var H=RegExp.prototype.test;function J(r,e){return H.call(r,e)}var F=/\S/;function W(r){return!J(F,r)}var q={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function G(r){return String(r).replace(/[&<>"'`=\/]/g,function(t){return q[t]})}var K=/\s*/,V=/\s+/,U=/\s*=/,z=/\s*\}/,Q=/#|\^|\/|>|\{|&|=|!/;function X(r,e){if(!r)return[];var t=!1,n=[],a=[],s=[],o=!1,i=!1,p="",u=0;function f(){if(o&&!i)for(;s.length;)delete a[s.pop()];else s=[];o=!1,i=!1}var v,m,N;function x(y){if(typeof y=="string"&&(y=y.split(V,2)),!_(y)||y.length!==2)throw new Error("Invalid tags: "+y);v=new RegExp(L(y[0])+"\\s*"),m=new RegExp("\\s*"+L(y[1])),N=new RegExp("\\s*"+L("}"+y[1]))}x(e||g.tags);for(var l=new T(r),w,h,d,k,M,b;!l.eos();){if(w=l.pos,d=l.scanUntil(v),d)for(var E=0,j=d.length;E"?M=[h,d,w,l.pos,p,u,t]:M=[h,d,w,l.pos],u++,a.push(M),h==="#"||h==="^")n.push(M);else if(h==="/"){if(b=n.pop(),!b)throw new Error('Unopened section "'+d+'" at '+w);if(b[1]!==d)throw new Error('Unclosed section "'+b[1]+'" at '+w)}else h==="name"||h==="{"||h==="&"?i=!0:h==="="&&x(d)}if(f(),b=n.pop(),b)throw new Error('Unclosed section "'+b[1]+'" at '+l.pos);return Z(Y(a))}function Y(r){for(var e=[],t,n,a=0,s=r.length;a0?n[n.length-1][4]:e;break;default:t.push(a)}return e}function T(r){this.string=r,this.tail=r,this.pos=0}T.prototype.eos=function(){return this.tail===""};T.prototype.scan=function(e){var t=this.tail.match(e);if(!t||t.index!==0)return"";var n=t[0];return this.tail=this.tail.substring(n.length),this.pos+=n.length,n};T.prototype.scanUntil=function(e){var t=this.tail.search(e),n;switch(t){case-1:n=this.tail,this.tail="";break;case 0:n="";break;default:n=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=n.length,n};function C(r,e){this.view=r,this.cache={".":this.view},this.parent=e}C.prototype.push=function(e){return new C(e,this)};C.prototype.lookup=function(e){var t=this.cache,n;if(t.hasOwnProperty(e))n=t[e];else{for(var a=this,s,o,i,p=!1;a;){if(e.indexOf(".")>0)for(s=a.view,o=e.split("."),i=0;s!=null&&i"?u=this.renderPartial(i,t,n,s):p==="&"?u=this.unescapedValue(i,t):p==="name"?u=this.escapedValue(i,t,s):p==="text"&&(u=this.rawValue(i)),u!==void 0&&(o+=u);return o};c.prototype.renderSection=function(e,t,n,a,s){var o=this,i="",p=t.lookup(e[1]);function u(m){return o.render(m,t,n,s)}if(p){if(_(p))for(var f=0,v=p.length;f0||!n)&&(s[o]=a+s[o]);return s.join(` -`)};c.prototype.renderPartial=function(e,t,n,a){if(n){var s=this.getConfigTags(a),o=P(n)?n(e[1]):n[e[1]];if(o!=null){var i=e[6],p=e[5],u=e[4],f=o;p==0&&u&&(f=this.indentPartial(o,u,i));var v=this.parse(f,s);return this.renderTokens(v,t,n,f,a)}}};c.prototype.unescapedValue=function(e,t){var n=t.lookup(e[1]);if(n!=null)return n};c.prototype.escapedValue=function(e,t,n){var a=this.getConfigEscape(n)||g.escape,s=t.lookup(e[1]);if(s!=null)return typeof s=="number"&&a===g.escape?String(s):a(s)};c.prototype.rawValue=function(e){return e[1]};c.prototype.getConfigTags=function(e){return S(e)?e:e&&typeof e=="object"?e.tags:void 0};c.prototype.getConfigEscape=function(e){if(e&&typeof e=="object"&&!S(e))return e.escape};var g={name:"mustache.js",version:"4.2.0",tags:["{{","}}"],clearCache:void 0,escape:void 0,parse:void 0,render:void 0,Scanner:void 0,Context:void 0,Writer:void 0,set templateCache(r){O.templateCache=r},get templateCache(){return O.templateCache}},O=new c;g.clearCache=function(){return O.clearCache()};g.parse=function(e,t){return O.parse(e,t)};g.render=function(e,t,n,a){if(typeof e!="string")throw new TypeError('Invalid template! Template should be a "string" but "'+A(e)+'" was given as the first argument for mustache#render(template, view, partials)');return O.render(e,t,n,a)};g.escape=G;g.Scanner=T;g.Context=C;g.Writer=c;var I=g;function R(r,e,t){return t!==null?I.render(t,r.properties):e===null?Object.keys(r.properties).map(a=>`${a}: ${r.properties[a]}`).join("
"):r.properties[e]}function ee(){if(typeof deck>"u")return;let r=new deck.JSONConfiguration({classes:deck});return new deck.JSONConverter({configuration:r})}var _=class{constructor(e){this._id=e.container,this._map=new maplibregl.Map(e),this._map.on("mouseover",()=>{this._map.getCanvas().style.cursor="pointer"}),this._map.on("mouseout",()=>{this._map.getCanvas().style.cursor=""}),this._map.addControl(new maplibregl.NavigationControl),this._JSONConverter=ee()}getMap(){return this._map}applyMapMethod(e,t){this._map[e](...t)}addControl(e,t,n){this._map.addControl(new maplibregl[e](t),n)}addMarker({lngLat:e,popup:t,options:n}){let a=new maplibregl.Marker(n).setLngLat(e);if(t){let s=new maplibregl.Popup(t.options).setHTML(t.text);a.setPopup(s)}a.addTo(this._map)}addLayer(e,t){this._map.addLayer(e,t),typeof Shiny<"u"&&this._map.on("click",e.id,n=>{console.log(n,n.features[0]);let a=e.id.replaceAll("-","_"),s=`${this._id}_layer_${a}`,o={props:n.features[0].properties,layer_id:e.id};console.log(s,o),Shiny.onInputChange(s,o)})}addPopup(e,t=null,n=null){let a={closeButton:!1},s=new maplibregl.Popup(a);this._map.on("click",e,o=>{let i=o.features[0],p=R(i,t,n);s.setLngLat(o.lngLat).setHTML(p).addTo(this._map)})}addTooltip(e,t=null,n=null){let a={closeButton:!1,closeOnClick:!1},s=new maplibregl.Popup(a);this._map.on("mousemove",e,o=>{let i=o.features[0],p=R(i,t,n);s.setLngLat(o.lngLat).setHTML(p).addTo(this._map)}),this._map.on("mouseleave",e,()=>{s.remove()})}setSourceData(e,t){this._map.getSource(e).setData(t)}addDeckOverlay(e){if(typeof this._JSONConverter>"u"){console.log("deck or JSONConverter is undefined");return}let t=e.map(s=>this._JSONConverter.convert(Object.assign(s,{onHover:({object:o})=>console.log(o)})));function n({object:s}){return s&&Object.entries(s).map(([o,i])=>`${o}: ${i}`).join(", ")}let a=new deck.MapboxOverlay({interleaved:!0,layers:t,getTooltip:n});this._map.addControl(a)}render(e){e.forEach(([t,n])=>{if(["addLayer","addPopup","addTooltip","addMarker","addPopup","addControl","setSourceData","addDeckOverlay"].includes(t)){console.log("Custom method",t,n),this[t](...n);return}console.log("Map method",t),this.applyMapMethod(t,n)})}};var te="0.1.0";console.log("pymaplibregl",te);typeof Shiny>"u"&&(window.pymaplibregl=function({mapOptions:r,calls:e}){let t="pymaplibregl",n=document.getElementById(t),a=new _(Object.assign({container:n.id},r));a.getMap().on("load",()=>{a.render(e)})});if(typeof Shiny<"u"){class r extends Shiny.OutputBinding{find(t){return t.find(".shiny-maplibregl-output")}renderValue(t,n){console.log("id:",t.id,"payload:",n);let a=window._maplibreWidget=new _(Object.assign({container:t.id},n.mapData.mapOptions)),s=a.getMap();s.on("load",()=>{a.render(n.mapData.calls)}),s.on("click",i=>{console.log(i);let p=`${t.id}`,u={coords:i.lngLat,point:i.point};console.log(p,u),Shiny.onInputChange(p,u)});let o=`pymaplibregl-${t.id}`;console.log(o),Shiny.addCustomMessageHandler(o,({id:i,calls:p})=>{console.log(i,p),a.render(p)})}}Shiny.outputBindings.register(new r,"shiny-maplibregl-output")}})(); +`)};c.prototype.renderPartial=function(e,t,n,a){if(n){var s=this.getConfigTags(a),o=P(n)?n(e[1]):n[e[1]];if(o!=null){var i=e[6],p=e[5],u=e[4],f=o;p==0&&u&&(f=this.indentPartial(o,u,i));var v=this.parse(f,s);return this.renderTokens(v,t,n,f,a)}}};c.prototype.unescapedValue=function(e,t){var n=t.lookup(e[1]);if(n!=null)return n};c.prototype.escapedValue=function(e,t,n){var a=this.getConfigEscape(n)||g.escape,s=t.lookup(e[1]);if(s!=null)return typeof s=="number"&&a===g.escape?String(s):a(s)};c.prototype.rawValue=function(e){return e[1]};c.prototype.getConfigTags=function(e){return _(e)?e:e&&typeof e=="object"?e.tags:void 0};c.prototype.getConfigEscape=function(e){if(e&&typeof e=="object"&&!_(e))return e.escape};var g={name:"mustache.js",version:"4.2.0",tags:["{{","}}"],clearCache:void 0,escape:void 0,parse:void 0,render:void 0,Scanner:void 0,Context:void 0,Writer:void 0,set templateCache(r){O.templateCache=r},get templateCache(){return O.templateCache}},O=new c;g.clearCache=function(){return O.clearCache()};g.parse=function(e,t){return O.parse(e,t)};g.render=function(e,t,n,a){if(typeof e!="string")throw new TypeError('Invalid template! Template should be a "string" but "'+A(e)+'" was given as the first argument for mustache#render(template, view, partials)');return O.render(e,t,n,a)};g.escape=G;g.Scanner=T;g.Context=C;g.Writer=c;var $=g;function R(r,e,t){return t!==null?$.render(t,r.properties):e===null?Object.keys(r.properties).map(a=>`${a}: ${r.properties[a]}`).join("
"):r.properties[e]}function ee(){if(typeof deck>"u")return;let r=new deck.JSONConfiguration({classes:deck});return new deck.JSONConverter({configuration:r})}var S=class{constructor(e){this._id=e.container,this._map=new maplibregl.Map(e),this._map.on("mouseover",()=>{this._map.getCanvas().style.cursor="pointer"}),this._map.on("mouseout",()=>{this._map.getCanvas().style.cursor=""}),this._map.addControl(new maplibregl.NavigationControl),this._JSONConverter=ee()}getMap(){return this._map}applyMapMethod(e,t){this._map[e](...t)}addControl(e,t,n){this._map.addControl(new maplibregl[e](t),n)}addMarker({lngLat:e,popup:t,options:n}){let a=new maplibregl.Marker(n).setLngLat(e);if(t){let s=new maplibregl.Popup(t.options).setHTML(t.text);a.setPopup(s)}a.addTo(this._map)}addLayer(e,t){this._map.addLayer(e,t),typeof Shiny<"u"&&this._map.on("click",e.id,n=>{console.log(n,n.features[0]);let a=e.id.replaceAll("-","_"),s=`${this._id}_layer_${a}`,o={props:n.features[0].properties,layer_id:e.id};console.log(s,o),Shiny.onInputChange(s,o)})}addPopup(e,t=null,n=null){let a={closeButton:!1},s=new maplibregl.Popup(a);this._map.on("click",e,o=>{let i=o.features[0],p=R(i,t,n);s.setLngLat(o.lngLat).setHTML(p).addTo(this._map)})}addTooltip(e,t=null,n=null){let a={closeButton:!1,closeOnClick:!1},s=new maplibregl.Popup(a);this._map.on("mousemove",e,o=>{let i=o.features[0],p=R(i,t,n);s.setLngLat(o.lngLat).setHTML(p).addTo(this._map)}),this._map.on("mouseleave",e,()=>{s.remove()})}setSourceData(e,t){this._map.getSource(e).setData(t)}addDeckOverlay(e){if(typeof this._JSONConverter>"u"){console.log("deck or JSONConverter is undefined");return}let t=e.map(s=>this._JSONConverter.convert(Object.assign(s,{onHover:({object:o})=>{if(console.log(o),typeof Shiny<"u"){let i=`${this._id}_layer_${s.id}`;console.log("deckInputName",i),Shiny.onInputChange(i,o)}}})));function n({object:s}){return s&&Object.entries(s).map(([o,i])=>`${o}: ${i}`).join(", ")}let a=new deck.MapboxOverlay({interleaved:!0,layers:t,getTooltip:n});this._map.addControl(a)}render(e){e.forEach(([t,n])=>{if(["addLayer","addPopup","addTooltip","addMarker","addPopup","addControl","setSourceData","addDeckOverlay"].includes(t)){console.log("Custom method",t,n),this[t](...n);return}console.log("Map method",t),this.applyMapMethod(t,n)})}};var te="0.1.0";console.log("pymaplibregl",te);typeof Shiny>"u"&&(window.pymaplibregl=function({mapOptions:r,calls:e}){let t="pymaplibregl",n=document.getElementById(t),a=new S(Object.assign({container:n.id},r));a.getMap().on("load",()=>{a.render(e)})});if(typeof Shiny<"u"){class r extends Shiny.OutputBinding{find(t){return t.find(".shiny-maplibregl-output")}renderValue(t,n){console.log("id:",t.id,"payload:",n);let a=window._maplibreWidget=new S(Object.assign({container:t.id},n.mapData.mapOptions)),s=a.getMap();s.on("load",()=>{a.render(n.mapData.calls)}),s.on("click",i=>{console.log(i);let p=`${t.id}`,u={coords:i.lngLat,point:i.point};console.log(p,u),Shiny.onInputChange(p,u)});let o=`pymaplibregl-${t.id}`;console.log(o),Shiny.addCustomMessageHandler(o,({id:i,calls:p})=>{console.log(i,p),a.render(p)})}}Shiny.outputBindings.register(new r,"shiny-maplibregl-output")}})(); /*! Bundled license information: mustache/mustache.mjs: diff --git a/srcjs/pymaplibregl.js b/srcjs/pymaplibregl.js index 6c3b969f..6048ba76 100644 --- a/srcjs/pymaplibregl.js +++ b/srcjs/pymaplibregl.js @@ -114,7 +114,16 @@ export default class PyMapLibreGL { const layers = deckLayers.map((deckLayer) => this._JSONConverter.convert( Object.assign(deckLayer, { - onHover: ({ object }) => console.log(object), + onHover: ({ object }) => { + console.log(object); + + // Add even listener + if (typeof Shiny !== "undefined") { + const inputName = `${this._id}_layer_${deckLayer.id}`; + console.log("deckInputName", inputName); + Shiny.onInputChange(inputName, object); + } + }, }), ), );