UNPKG

@expofp/floorplan

Version:

Interactive floor plan library for expos and events

2 lines (1 loc) • 4.34 kB
import{LngLatBounds as D,MercatorCoordinate as E}from"maplibre-gl";import{fpGeo as I}from"../../../data/fpGeo";import{svgArea as x}from"../../../data/svg";import{uiState as z}from"../../../store";import{convertLocalToGps as u}from"../../../utils/gps";import{planBearing as N}from"../../../utils/planBearing";export const MAP_BOUNDS_PADDING_FACTOR=3,MAP_BOUNDS_MIN_PADDING_DEGREES=.02,INITIAL_FIT_ZOOM_ADJUSTMENT=.15;const T=1.42,F=.35,S=.9,A=.85,P=8,B=.05;export function deriveVenueMapBounds(t){const n=[[x.min.x,x.min.y],[x.max.x,x.min.y],[x.max.x,x.max.y],[x.min.x,x.max.y]].map(([c,l])=>u(c,l,t));if(!n.every(([c,l])=>Number.isFinite(c)&&Number.isFinite(l)))return;const e=n.map(([c])=>c),o=n.map(([,c])=>c),i=Math.min(...e),r=Math.max(...e),s=Math.min(...o),a=Math.max(...o),m=Math.max((r-i)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES),h=Math.max((a-s)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES);return[[i-m,s-h],[r+m,a+h]]}function O(t,n,e,o){const i=Math.min(t.getZoom(),n),r=(e-i)*Math.min(1,o/T);return i+r>=t.getMinZoom()-B}function w(t,n,e){if(O(t,n,e,T))return T;if(!O(t,n,e,F))return null;let o=F,i=T;for(let r=0;r<P;r++){const s=(o+i)/2;O(t,n,e,s)?o=s:i=s}return o}export function getLocalRectGeoBounds(t,n){const e=[u(t.min.x,t.min.y,n),u(t.max.x,t.min.y,n),u(t.max.x,t.max.y,n),u(t.min.x,t.max.y,n)],o=e.map(([r])=>r),i=e.map(([,r])=>r);return[[Math.min(...o),Math.min(...i)],[Math.max(...o),Math.max(...i)]]}const R=512;export function cameraForLocalRect(t,n,e,o,i){const r=[u(t.min.x,t.min.y,n),u(t.max.x,t.min.y,n),u(t.max.x,t.max.y,n),u(t.min.x,t.max.y,n)].map(([M,p])=>E.fromLngLat({lng:M,lat:p}));if(!r.every(({x:M,y:p})=>Number.isFinite(M)&&Number.isFinite(p)))return null;const s=-e*Math.PI/180,a=Math.cos(s),m=Math.sin(s),h=r.map(({x:M,y:p})=>M*a-p*m),c=r.map(({x:M,y:p})=>M*m+p*a),l=Math.max(...h)-Math.min(...h),y=Math.max(...c)-Math.min(...c);if(l<=0||y<=0)return null;const b=o.width-i.left-i.right,f=o.height-i.top-i.bottom;if(b<=0||f<=0)return null;const d=Math.min(b/(l*R),f/(y*R));if(!(d>0))return null;const g=R*d,L=(Math.min(...h)+Math.max(...h))/2-(i.left-i.right)/2/g,_=(Math.min(...c)+Math.max(...c))/2-(i.top-i.bottom)/2/g,{lng:v,lat:C}=new E(L*a+_*m,-L*m+_*a).toLngLat();return{center:[v,C],zoom:Math.log2(d)}}function U(t,n){return{top:t.top+n.top,bottom:t.bottom+n.bottom,left:t.left+n.left,right:t.right+n.right}}export function getVisibleRectFitPadding(t=0){const n=z.canvasVisibleRectPx,e=z.screenSize;return n?{top:Math.max(0,n.min.y)+t,bottom:Math.max(0,e.height-n.max.y)+t,left:Math.max(0,n.min.x)+t,right:Math.max(0,e.width-n.max.x)+t}:{top:t,bottom:t,left:t,right:t}}export function isLngLatInVisibleViewport(t,n,e){const o=t.project(n),i=t.getCanvas();return o.x>=e.left&&o.x<=i.clientWidth-e.right&&o.y>=e.top&&o.y<=i.clientHeight-e.bottom}export function deriveGeoConfig(){if(!I?.properties?.config)return null;const t=I.properties.config,n=(t.p0.lng+t.p2.lng)/2,e=(t.p0.lat+t.p2.lat)/2,o=N(t.p0,t.p2),i=Number.isFinite(o)?o:t.bearing??0;return{center:[n,e],bearing:i,zoom:16,gpsConfig:t}}export function fitMapToLocalRect(t,n,e,o={}){if(!t||!n||!e||n.size.height===1/0||n.size.width===1/0||n.size.height<=0||n.size.width<=0)return;const i=getLocalRectGeoBounds(n,e.gpsConfig),r=t.getCanvas(),s=o.paddingPercent==null?getVisibleRectFitPadding(o.padding??50):U(getVisibleRectFitPadding(0),{top:r.clientHeight*o.paddingPercent,bottom:r.clientHeight*o.paddingPercent,left:r.clientWidth*o.paddingPercent,right:r.clientWidth*o.paddingPercent}),a=cameraForLocalRect(n,e.gpsConfig,e.bearing,{width:r.clientWidth,height:r.clientHeight},s);if(!a){t.fitBounds(i,{padding:s,bearing:e.bearing,essential:!0});return}const m=t.project(t.getCenter()),h=t.project(a.center),c=Math.max(t.getCanvas().clientWidth,t.getCanvas().clientHeight,1),l=Math.hypot(h.x-m.x,h.y-m.y)/c,y=Math.abs(t.getZoom()-a.zoom),b=o.duration??Math.min(2800,500+l*450+y*150),f={center:a.center,zoom:a.zoom,bearing:e.bearing,duration:b,essential:!0};if(l<=1.2&&y<=1.5){t.easeTo(f);return}const d=t.getBounds().extend(D.convert(i)),g=t.cameraForBounds(d,{padding:s,bearing:e.bearing});if(!g?.center||typeof g.zoom!="number"||g.zoom>=t.getZoom()-.2){t.easeTo(f);return}const L=w(t,a.zoom,g.zoom);if(L!==null){const _=Math.max(F,L*S),v=Math.round(b*A);t.flyTo({...f,curve:_,duration:v});return}t.easeTo(f)}