@bitalltech-maplibre/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("maplibre-gl")):"function"==typeof define&&define.amd?define(["exports","maplibre-gl"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).BitAllTechMaplibreCore={},t.maplibregl)}(this,function(t,e){"use strict";const i={},a=()=>({...i}),n="https://tiles.openfreemap.org/styles",r=(t,e,i)=>({type:t,label:e,style:`${n}/${i}`}),o={"openfreemap-liberty":r("openfreemap-liberty","OpenFreeMap Liberty","liberty"),"openfreemap-bright":r("openfreemap-bright","OpenFreeMap Bright","bright"),"openfreemap-positron":r("openfreemap-positron","OpenFreeMap Positron","positron"),"openfreemap-dark":r("openfreemap-dark","OpenFreeMap Dark","dark"),"openfreemap-fiord":r("openfreemap-fiord","OpenFreeMap Fiord","fiord")},l=Object.keys(o),c=(t="openfreemap-liberty")=>o[t].style,s=["0","1","2","3","4","5","6","7"],p=(t,e)=>{const i=(t=>{const e=t||a().tdtToken;if(!e)throw new Error("Tianditu token is required. Pass token or call setMaplibreToolsConfig({ tdtToken }).");return e})(e);return s.map(e=>`https://t${e}.tianditu.gov.cn/DataServer?T=${t}&x={x}&y={y}&l={z}&tk=${i}`)},d=(t,e={})=>({type:"raster",tiles:p(t,e.token),tileSize:256,minzoom:0,maxzoom:18,attribution:"&copy; 天地图"}),h=(t={})=>{const e=!1!==t.label,i={"tdt-image":d("img_w",t)},a=[{id:"tdt-image",type:"raster",source:"tdt-image"}];return e&&(i["tdt-image-label"]=d("cia_w",t),a.push({id:"tdt-image-label",type:"raster",source:"tdt-image-label"})),{version:8,sources:i,layers:a}},f=[...Object.keys(o),"tdt-image","tdt-image-label"],y=t=>f.includes(t),u=(t="openfreemap-liberty",e={})=>"tdt-image"===t?h({...e,label:!1}):"tdt-image-label"===t?h({...e,label:!0}):c(t),m=t=>t*Math.PI/180,g=t=>180*t/Math.PI,M=t=>(t%360+360)%360,b=(t,e,i)=>{const a=e/6378137,n=m(i),r=m(t[1]),o=m(t[0]),l=Math.asin(Math.sin(r)*Math.cos(a)+Math.cos(r)*Math.sin(a)*Math.cos(n)),c=o+Math.atan2(Math.sin(n)*Math.sin(a)*Math.cos(r),Math.cos(a)-Math.sin(r)*Math.sin(l));return[(s=g(c),s>180?s-360:s<-180?s+360:s),g(l)];var s},k=(t,e,i=64)=>{const a=((t,e)=>{const i=M(e)-M(t);return i<=0?i+360:i})(t,e),n=Math.max(12,Math.ceil(i*a/360));return Array.from({length:n+1},(e,i)=>M(t+a*i/n))},v=(t,e,i=64)=>(t=>{if(0===t.length)return t;const[e,i]=t[0],a=t[t.length-1];return a[0]===e&&a[1]===i?t:[...t,[e,i]]})(Array.from({length:i},(a,n)=>b(t,e,360*n/i))),A=(t,e,i=64)=>({type:"Polygon",coordinates:[v(t,e,i)]}),$=(t,e,i=64)=>({type:"LineString",coordinates:v(t,e,i)}),w=(t,e,i,a,n=64)=>{const r=k(i,a,n).map(i=>b(t,e,i));return{type:"Polygon",coordinates:[[t,...r,t]]}},x=(t,e,i,a,n=64)=>({type:"LineString",coordinates:k(i,a,n).map(i=>b(t,e,i))}),F=(t,e,i)=>({type:"LineString",coordinates:[t,b(t,e,i)]}),O=(t,e)=>({type:"Feature",geometry:t,properties:e}),q=t=>({type:"FeatureCollection",features:t}),S=(t,e,i)=>{const a=i?"visible":"none";e.forEach(e=>{t.getLayer(e)&&t.setLayoutProperty(e,"visibility",a)})},D=(t,e,i)=>{const a=e.id,n=`${a}-source`;let r,o={...e},l=[],c=[n],s=!1,p=!1;const d=()=>{null==r||r(),r=void 0,[...l].reverse().forEach(e=>{((t,e)=>{t.getLayer(e)&&t.removeLayer(e)})(t,e)}),[...c].reverse().forEach(e=>{((t,e)=>{t.getSource(e)&&t.removeSource(e)})(t,e)}),l=[],c=[n]},h=e=>{const i=t.getSource(n);i&&i.setData(e)},f=()=>{var e,a;if(s)return;d();const p=i(o);t.addSource(n,{type:"geojson",data:p.data}),null==(e=p.canvasSources)||e.forEach(e=>{t.addSource(e.id,e.source)}),c=[n,...(null==(a=p.canvasSources)?void 0:a.map(t=>t.id))||[]],l=p.layers.map(t=>t.id),p.layers.forEach(e=>{var i;const a="raster"===e.type&&(null==(i=p.canvasSources)?void 0:i[0])?p.canvasSources[0].id:n;t.addLayer({...e,source:a},o.beforeId)}),S(t,l,!1!==o.visible),p.startAnimation&&(r=p.startAnimation({getOptions:()=>o,setData:h})||void 0)},y=()=>{p&&!s&&t.isStyleLoaded()&&(p=!1,t.off("styledata",y),f())},u=()=>{s||(t.isStyleLoaded()?(p&&(p=!1,t.off("styledata",y)),f()):p||(p=!0,t.on("styledata",y)))};return u(),{id:a,update(t){s||(o={...o,...t,id:a},u())},show(){s||(o={...o,visible:!0},S(t,l,!0))},hide(){s||(o={...o,visible:!1},S(t,l,!1))},remove(){s||(s=!0,p&&(p=!1,t.off("styledata",y)),d())}}},j=(t,e=0)=>{const i=Math.max(10,t.radius??70),a=Math.max(i,t.maxRadius??2.3*i),n=Math.max(1,t.pulseCount??2),r=Math.max(1,t.lineWidth??2),o=t.pulseOpacity??.9,l=[O(A(t.center,i),{kind:"core"})];for(let c=0;c<n;c+=1){const s=(e+c/n)%1,p=i+(a-i)*s;l.push(O($(t.center,p),{kind:"pulse",opacity:o*(1-s),width:r*(1-.35*s)}))}return q(l)},T=t=>{const e=t.color||"#ff3b30",i=t.fillColor||e;return{data:j(t),layers:[{id:`${t.id}-core`,type:"fill",filter:["==",["get","kind"],"core"],paint:{"fill-color":i,"fill-opacity":t.fillOpacity??.28}},{id:`${t.id}-pulse`,type:"line",filter:["==",["get","kind"],"pulse"],paint:{"line-color":e,"line-opacity":["coalesce",["get","opacity"],t.pulseOpacity??.9],"line-width":["coalesce",["get","width"],t.lineWidth??2]}}],startAnimation({getOptions:t,setData:e}){const i=Math.max(400,t().duration??1800);let a=0;const n=performance.now(),r=o=>{const l=t();e(j(l,(o-n)%i/i)),a=requestAnimationFrame(r)};return a=requestAnimationFrame(r),()=>{cancelAnimationFrame(a)}}}},L=(t,e=0)=>{var i,a;const n=Math.max(16,t.radius??110),r=Math.max(0,t.pulseScale??.16),o=(1-Math.cos(e*Math.PI*2))/2,l=n*(1+r*o),c=1.28*l,s=Math.max(1,t.ringCount??(null==(i=t.radii)?void 0:i.length)??3),p=Math.max(2.2*l,t.maxRadius??((null==(a=t.radii)?void 0:a.length)?Math.max(...t.radii):n*(2.5*s))),d=p/s,h=[O(A(t.center,c),{kind:"halo",opacity:(t.haloOpacity??.16)*(.75+.65*o)}),O(A(t.center,l),{kind:"core",opacity:(t.fillOpacity??.28)*(.88+.2*o)}),O($(t.center,1.06*l),{kind:"core-ring",opacity:(t.lineOpacity??.95)*(.8+.2*o),width:Math.max(1,(t.lineWidth??3)*(.92+.12*o))})];for(let f=0;f<s;f+=1){const i=(f+e+1)*d%p||p,a=i/p;h.push(O($(t.center,i),{kind:"ring",opacity:Math.max(.18,(t.lineOpacity??.95)*(1-.42*a)),width:Math.max(1,(t.lineWidth??3)*(1-.18*a))}))}return q(h)},z=t=>{const e=t.color||"#ef4444",i=t.fillColor||e;return{data:L(t),layers:[{id:`${t.id}-halo`,type:"fill",filter:["==",["get","kind"],"halo"],paint:{"fill-color":i,"fill-opacity":["coalesce",["get","opacity"],t.haloOpacity??.16]}},{id:`${t.id}-core`,type:"fill",filter:["==",["get","kind"],"core"],paint:{"fill-color":i,"fill-opacity":["coalesce",["get","opacity"],t.fillOpacity??.28]}},{id:`${t.id}-rings`,type:"line",filter:["any",["==",["get","kind"],"ring"]],paint:{"line-color":e,"line-opacity":["coalesce",["get","opacity"],t.lineOpacity??.95],"line-width":["coalesce",["get","width"],t.lineWidth??3]}}],startAnimation({getOptions:t,setData:e}){const i=Math.max(600,t().duration??2e3);let a=0;const n=performance.now(),r=o=>{const l=t();e(L(l,(o-n)%i/i)),a=requestAnimationFrame(r)};return a=requestAnimationFrame(r),()=>{cancelAnimationFrame(a)}}}},P=(t,e,i)=>Math.min(i,Math.max(e,t)),I=t=>(t%360+360)%360,N=(t,e)=>{const i=(t=>{const e=t.trim(),i=e.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);if(i){const t=i[1],e=3===t.length?t.split("").map(t=>t+t).join(""):t;return[parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16)]}const a=e.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i);if(a)return[P(Number(a[1]),0,255),P(Number(a[2]),0,255),P(Number(a[3]),0,255)]})(t);return i?`rgba(${i[0]}, ${i[1]}, ${i[2]}, ${P(e,0,1)})`:t},B=(t,e)=>{const i=b(t,e,0)[1],a=b(t,e,90)[0],n=b(t,e,180)[1],r=b(t,e,270)[0];return[[r,i],[a,i],[a,n],[r,n]]},C=t=>{var e;const i=null==(e=t.gradient)?void 0:e.colors;return Array.isArray(i)&&i.length>=2?i:void 0},_=(t,e,i=0)=>{const a=t.getContext("2d"),n=C(e);if(!a||!e.gradient||!n)return;const r=t.width,o=r/2,l=o-2,c=e.startAngle+i,s=((t,e)=>{const i=I(e)-I(t);return i<=0?i+360:i})(c,e.endAngle+i),p=(c-90)*Math.PI/180;const d=p+s*Math.PI/180,h=e.gradient.opacity??e.opacity??.28,f=e.gradient.centerOpacity??e.gradient.tailOpacity??.25*h,y=e.gradient.edgeOpacity??e.gradient.headOpacity??h,u=a.createRadialGradient(o,o,0,o,o,l);n.forEach((t,e)=>{const i=e/Math.max(1,n.length-1),a=f+(y-f)*i;u.addColorStop(i,N(t,a))}),a.clearRect(0,0,r,r),a.save(),a.beginPath(),a.moveTo(o,o),a.arc(o,o,l,p,d,!1),a.closePath(),a.clip(),a.fillStyle=u,a.fillRect(0,0,r,r),a.restore()},E=t=>{if(!C(t))return;const e=(()=>{const t=document.createElement("canvas");return t.width=768,t.height=768,t})();return _(e,t),e},G=(t,e,i)=>C(t)?[]:[O(w(t.center,t.radius,e,i),{kind:"sector",color:t.color||"#ff453a",opacity:t.opacity??.28})],H=(t,e=0)=>{const i=t.startAngle+e,a=t.endAngle+e,n=[...G(t,i,a),O(F(t.center,t.radius,i),{kind:"frame"}),O(F(t.center,t.radius,a),{kind:"frame"})];return q(n)},J=t=>{const e=E(t),i=e?{id:`${t.id}-sector-fill`,type:"raster",paint:{"raster-opacity":1,"raster-fade-duration":0}}:{id:`${t.id}-sector-fill`,type:"fill",filter:["==",["get","kind"],"sector"],paint:{"fill-color":["coalesce",["get","color"],t.color||"#ff453a"],"fill-opacity":["coalesce",["get","opacity"],t.opacity??.28],"fill-antialias":!1}};return{data:H(t),canvasSources:e?[{id:`${t.id}-canvas-source`,source:{type:"canvas",canvas:e,coordinates:B(t.center,t.radius),animate:Boolean(t.rotationSpeed&&0!==t.rotationSpeed)}}]:void 0,layers:[i,{id:`${t.id}-sector-frame`,type:"line",filter:["==",["get","kind"],"frame"],paint:{"line-color":t.outlineColor||t.color||"#ff453a","line-opacity":t.outlineOpacity??.95,"line-width":t.outlineWidth??2}}],startAnimation:t.rotationSpeed&&0!==t.rotationSpeed?({getOptions:t,setData:i})=>{const a=performance.now();let n=0;const r=o=>{const l=t(),c=(o-a)/1e3*(l.rotationSpeed||0);e&&_(e,l,c),i(H(l,c)),n=requestAnimationFrame(r)};return n=requestAnimationFrame(r),()=>{cancelAnimationFrame(n)}}:void 0}},K=(t,e)=>{const i=Math.max(40,t.radius),a=t.direction??270,n=Math.min(180,Math.max(8,t.spread??72)),r=Math.max(1,t.lineCount??7),o=Math.max(20,t.lineSpacing??Math.max(80,i/9)),l=e??0,c=Math.max(0,Math.min(.35*i,t.innerRadius??Math.min(.4*o,120))),s=a-n/2,p=a+n/2,d=[];for(let h=0;h<r;h+=1){const e=c+l+h*o;if(e>i)continue;const a=e/i,n=1-h/Math.max(1,r);d.push(O(x(t.center,e,s,p),{kind:"directional-pulse-line",opacity:Math.max(.08,(t.opacity??.92)*(.42+.58*n)*(1-.28*a)),width:Math.max(1,(t.lineWidth??2.8)*(.86+.24*n)*(1-.08*a))}))}return q(d)},Q=t=>({data:K(t),layers:[{id:`${t.id}-directional-pulse`,type:"line",filter:["==",["get","kind"],"directional-pulse-line"],layout:{"line-cap":"round","line-join":"round"},paint:{"line-color":t.color||"#ef4444","line-opacity":["coalesce",["get","opacity"],t.opacity??.92],"line-width":["coalesce",["get","width"],t.lineWidth??2.8]}}],startAnimation:t.speed&&t.speed>0?({getOptions:t,setData:e})=>{const i=performance.now();let a=0;const n=r=>{const o=t(),l=Math.max(40,o.radius),c=Math.max(20,o.lineSpacing??Math.max(80,l/9)),s=(r-i)/1e3*(o.speed??0)%c;e(K(o,s)),a=requestAnimationFrame(n)};return a=requestAnimationFrame(n),()=>{cancelAnimationFrame(a)}}:void 0}),R=(t,e=0)=>{var i;const a=Math.max(0,t.ringCount??4),n=Math.max(1,t.trailCount??8),r=Math.max(12,t.sweepAngle??42),o=.22*r,l=t.tailOpacity??.04,c=t.headOpacity??Math.max(.24,t.opacity??.3),s=(t.sweepStartAngle??0)+e,p=!1!==t.showCrosshair,d=!1!==t.showDistanceLabels,h=Math.max(20,t.coreRadius??Math.min(160,.035*t.radius)),f=[];for(let y=a;y>=1;y-=1){const e=t.radius*y/a;if(f.push(O($(t.center,e),{kind:"ring"})),d){const a=(null==(i=t.distanceLabelFormatter)?void 0:i.call(t,e,y))??`${Math.round(e)}`;[{bearing:0,textAnchor:"bottom"},{bearing:90,textAnchor:"left"},{bearing:180,textAnchor:"top"},{bearing:270,textAnchor:"right"}].forEach(i=>{f.push(O({type:"Point",coordinates:b(t.center,e,i.bearing)},{kind:"distance-label",text:a,textAnchor:i.textAnchor}))})}}p&&f.push(O({type:"LineString",coordinates:[b(t.center,t.radius,180),b(t.center,t.radius,0)]},{kind:"crosshair"}),O({type:"LineString",coordinates:[b(t.center,t.radius,270),b(t.center,t.radius,90)]},{kind:"crosshair"})),f.push(O(A(t.center,h),{kind:"core"}));for(let y=n-1;y>=0;y-=1){const e=s-o*y,i=e+r,a=(n-y)/n,p=l+(c-l)*a*a;f.push(O(w(t.center,t.radius,e,i),{kind:"sweep",opacity:p}))}return f.push(O(w(t.center,t.radius,s+.42*r,s+r),{kind:"head",opacity:Math.min(1,c+.08)})),q(f)},U=t=>({data:R(t),layers:[{id:`${t.id}-radar-trail`,type:"fill",filter:["==",["get","kind"],"sweep"],paint:{"fill-color":t.color||"#22c55e","fill-opacity":["coalesce",["get","opacity"],t.opacity??.32]}},{id:`${t.id}-radar-rings`,type:"line",filter:["==",["get","kind"],"ring"],paint:{"line-color":t.ringColor||t.color||"#22c55e","line-opacity":t.ringOpacity??.95,"line-width":t.ringWidth??2}},{id:`${t.id}-radar-crosshair`,type:"line",filter:["==",["get","kind"],"crosshair"],paint:{"line-color":t.crosshairColor||t.ringColor||t.color||"#22c55e","line-opacity":t.crosshairOpacity??.5,"line-width":t.crosshairWidth??1.4}},{id:`${t.id}-radar-distance-labels`,type:"symbol",filter:["==",["get","kind"],"distance-label"],layout:{"text-field":["get","text"],"text-size":t.distanceLabelSize??12,"text-anchor":["get","textAnchor"],"text-allow-overlap":!0,"text-ignore-placement":!0},paint:{"text-color":t.distanceLabelColor||t.ringColor||t.color||"#22c55e","text-opacity":t.distanceLabelOpacity??.92,"text-halo-color":t.distanceLabelHaloColor||"rgba(15, 23, 42, 0.42)","text-halo-width":1}}],startAnimation({getOptions:t,setData:e}){const i=performance.now();let a=0;const n=r=>{const o=t(),l=(r-i)/1e3*(o.rotationSpeed??36);e(R(o,l)),a=requestAnimationFrame(n)};return a=requestAnimationFrame(n),()=>{cancelAnimationFrame(a)}}}),V=(t,e)=>t?"string"==typeof t&&y(t)?u(t,{token:e}):t:u("openfreemap-liberty");t.maplibregl=e,t.BASE_MAP_TYPES=f,t.OPENFREEMAP_STYLES=o,t.OPENFREEMAP_STYLE_BASE_URL=n,t.OPENFREEMAP_STYLE_TYPES=l,t.TDT_STYLE_TYPES=["tdt-image","tdt-image-label"],t.addDirectionalPulse=(t,e)=>D(t,e,Q),t.addPulseMarker=(t,e)=>D(t,e,T),t.addRadarSweep=(t,e)=>D(t,e,U),t.addRingPulseMarker=(t,e)=>D(t,e,z),t.addSectorScan=(t,e)=>D(t,e,J),t.createMap=t=>{const{style:i,tdtToken:a,...n}=t;return new e.Map({...n,style:V(i,a)})},t.createTiandituImageStyle=h,t.createTiandituRasterSource=d,t.getBaseMapStyle=u,t.getMaplibreToolsConfig=a,t.getOpenFreeMapStyle=c,t.isBaseMapType=y,t.setBaseMap=(t,e,i={})=>{const{diff:a=!1,...n}=i;t.setStyle(u(e,n),{diff:a})},t.setMaplibreToolsConfig=t=>{Object.assign(i,t)},Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,16 @@
1
+ import type { Map, StyleSpecification } from "maplibre-gl";
2
+ import { type OpenFreeMapStyleType } from "./openfreemap";
3
+ import { type TiandituStyleOptions } from "./tianditu";
4
+ export type BaseMapType = OpenFreeMapStyleType | "tdt-image" | "tdt-image-label";
5
+ export interface BaseMapOptions extends TiandituStyleOptions {
6
+ /** 透传给 map.setStyle;false 会完整重载样式,true 会尝试差量更新。 */
7
+ diff?: boolean;
8
+ }
9
+ /** 当前包支持的所有底图类型。 */
10
+ export declare const BASE_MAP_TYPES: BaseMapType[];
11
+ export declare const isBaseMapType: (type: string) => type is BaseMapType;
12
+ /** 根据底图类型返回 MapLibre style。OpenFreeMap 返回 URL,天地图返回内联 style。 */
13
+ export declare const getBaseMapStyle: (type?: BaseMapType, options?: TiandituStyleOptions) => string | StyleSpecification;
14
+ export declare const setBaseMap: (map: Map, type: BaseMapType, options?: BaseMapOptions) => void;
15
+ export * from "./openfreemap";
16
+ export * from "./tianditu";
@@ -0,0 +1,11 @@
1
+ export declare const OPENFREEMAP_STYLE_BASE_URL = "https://tiles.openfreemap.org/styles";
2
+ /** OpenFreeMap 官方样式别名。 */
3
+ export type OpenFreeMapStyleType = "openfreemap-liberty" | "openfreemap-bright" | "openfreemap-positron" | "openfreemap-dark" | "openfreemap-fiord";
4
+ export interface OpenFreeMapStyleConfig {
5
+ type: OpenFreeMapStyleType;
6
+ label: string;
7
+ style: string;
8
+ }
9
+ export declare const OPENFREEMAP_STYLES: Record<OpenFreeMapStyleType, OpenFreeMapStyleConfig>;
10
+ export declare const OPENFREEMAP_STYLE_TYPES: OpenFreeMapStyleType[];
11
+ export declare const getOpenFreeMapStyle: (type?: OpenFreeMapStyleType) => string;
@@ -0,0 +1,15 @@
1
+ import type { RasterSourceSpecification, StyleSpecification } from "maplibre-gl";
2
+ /** 天地图图层类型:影像底图或影像注记。 */
3
+ export type TiandituLayerType = "tdt-image" | "tdt-image-label";
4
+ export interface TiandituOptions {
5
+ /** 天地图 token;不传时读取 setMaplibreToolsConfig 设置的全局 token。 */
6
+ token?: string;
7
+ }
8
+ export interface TiandituStyleOptions extends TiandituOptions {
9
+ /** 是否叠加注记图层,默认 true。 */
10
+ label?: boolean;
11
+ }
12
+ export declare const TDT_STYLE_TYPES: readonly ["tdt-image", "tdt-image-label"];
13
+ export declare const createTiandituRasterSource: (tileType: "img_w" | "cia_w", options?: TiandituOptions) => RasterSourceSpecification;
14
+ /** 创建 MapLibre 可直接使用的天地图影像 style。 */
15
+ export declare const createTiandituImageStyle: (options?: TiandituStyleOptions) => StyleSpecification;
@@ -0,0 +1,8 @@
1
+ export interface MaplibreToolsConfig {
2
+ /** 全局天地图 token;不想每次调用都传 token 时可在这里设置。 */
3
+ tdtToken?: string;
4
+ }
5
+ /** 合并更新全局配置。 */
6
+ export declare const setMaplibreToolsConfig: (options: MaplibreToolsConfig) => void;
7
+ /** 返回配置副本,避免外部直接修改内部单例对象。 */
8
+ export declare const getMaplibreToolsConfig: () => MaplibreToolsConfig;
@@ -0,0 +1,32 @@
1
+ export type LngLatTuple = [number, number];
2
+ export declare const normalizeAngle: (angle: number) => number;
3
+ /** 从中心点按距离和方位角推算目标点,单位米/度。 */
4
+ export declare const getDestination: (center: LngLatTuple, distance: number, bearing: number) => LngLatTuple;
5
+ /** 计算两点球面距离,单位米。 */
6
+ export declare const getDistance: (start: LngLatTuple, end: LngLatTuple) => number;
7
+ /** 计算从 start 指向 end 的方位角,结果为 0-360 度。 */
8
+ export declare const getBearing: (start: LngLatTuple, end: LngLatTuple) => number;
9
+ /** 创建圆形外环坐标,圆在 GeoJSON 中用多边形近似。 */
10
+ export declare const createCircleCoordinates: (center: LngLatTuple, radius: number, segmentCount?: number) => LngLatTuple[];
11
+ export declare const createCirclePolygon: (center: LngLatTuple, radius: number, segmentCount?: number) => GeoJSON.Polygon;
12
+ export declare const createCircleLine: (center: LngLatTuple, radius: number, segmentCount?: number) => GeoJSON.LineString;
13
+ /** 创建扇形面:中心点 + 弧线点 + 中心点。 */
14
+ export declare const createSectorPolygon: (center: LngLatTuple, radius: number, startAngle: number, endAngle: number, segmentCount?: number) => GeoJSON.Polygon;
15
+ /** 创建扇形环带,用于模拟从圆心到外缘的径向渐变。 */
16
+ export declare const createSectorBandPolygon: (center: LngLatTuple, innerRadius: number, outerRadius: number, startAngle: number, endAngle: number, segmentCount?: number) => GeoJSON.Polygon;
17
+ /** 创建圆弧线,常用于扫描框线或脉冲线。 */
18
+ export declare const createArcLine: (center: LngLatTuple, radius: number, startAngle: number, endAngle: number, segmentCount?: number) => GeoJSON.LineString;
19
+ /** 从中心向指定方向创建一条半径线。 */
20
+ export declare const createRayLine: (center: LngLatTuple, radius: number, bearing: number) => GeoJSON.LineString;
21
+ /** 创建方向波束的面和中心线,用于后续扩展定向效果。 */
22
+ export declare const createBeamGeometry: (options: {
23
+ center: LngLatTuple;
24
+ target?: LngLatTuple;
25
+ bearing?: number;
26
+ distance?: number;
27
+ startWidth: number;
28
+ endWidth: number;
29
+ }) => {
30
+ polygon: GeoJSON.Polygon;
31
+ centerLine: GeoJSON.LineString;
32
+ };
@@ -0,0 +1,2 @@
1
+ export { addDirectionalPulse, addPulseMarker, addRingPulseMarker, addRadarSweep, addSectorScan, } from "./low-altitude";
2
+ export type { DirectionalPulseOptions, MapEffectController, PulseMarkerOptions, RingPulseMarkerOptions, RadarSweepOptions, SectorScanOptions, } from "./low-altitude";
@@ -0,0 +1,126 @@
1
+ import type { Map } from "maplibre-gl";
2
+ import { type LngLatTuple } from "./geometry";
3
+ interface BaseEffectOptions {
4
+ /** 特效 id;会派生出 sourceId 和多个 layerId。 */
5
+ id: string;
6
+ /** 特效中心点,经纬度。 */
7
+ center: LngLatTuple;
8
+ /** 插入到指定图层之前。 */
9
+ beforeId?: string;
10
+ /** 初始是否可见,默认可见。 */
11
+ visible?: boolean;
12
+ }
13
+ /** addXxxEffect 返回的控制器,用于更新、显隐和移除特效。 */
14
+ export interface MapEffectController<Options> {
15
+ id: string;
16
+ update: (options: Partial<Omit<Options, "id">>) => void;
17
+ show: () => void;
18
+ hide: () => void;
19
+ remove: () => void;
20
+ }
21
+ /** 单点扩散脉冲:适合告警点、事件点、目标点高亮。 */
22
+ export interface PulseMarkerOptions extends BaseEffectOptions {
23
+ radius?: number;
24
+ maxRadius?: number;
25
+ color?: string;
26
+ fillColor?: string;
27
+ fillOpacity?: number;
28
+ pulseOpacity?: number;
29
+ lineWidth?: number;
30
+ pulseCount?: number;
31
+ duration?: number;
32
+ }
33
+ /** 多环脉冲:比普通脉冲更强调中心和外扩环。 */
34
+ export interface RingPulseMarkerOptions extends BaseEffectOptions {
35
+ radius?: number;
36
+ radii?: number[];
37
+ maxRadius?: number;
38
+ ringCount?: number;
39
+ color?: string;
40
+ fillColor?: string;
41
+ fillOpacity?: number;
42
+ haloOpacity?: number;
43
+ lineOpacity?: number;
44
+ lineWidth?: number;
45
+ duration?: number;
46
+ pulseScale?: number;
47
+ }
48
+ /** 扇形扫描渐变配置。colors 会从圆心沿半径方向过渡到外缘。 */
49
+ export interface SectorScanGradientOptions {
50
+ colors?: string[];
51
+ steps?: number;
52
+ opacity?: number;
53
+ /** 圆心附近透明度;不传时使用 tailOpacity 或基础透明度的 25%。 */
54
+ centerOpacity?: number;
55
+ /** 外缘透明度;不传时使用 headOpacity 或基础透明度。 */
56
+ edgeOpacity?: number;
57
+ /** 兼容旧配置:等同于 centerOpacity。 */
58
+ tailOpacity?: number;
59
+ /** 兼容旧配置:等同于 edgeOpacity。 */
60
+ headOpacity?: number;
61
+ }
62
+ /** 扇形扫描:给定起止角度,可选旋转速度和分段渐变。 */
63
+ export interface SectorScanOptions extends BaseEffectOptions {
64
+ radius: number;
65
+ startAngle: number;
66
+ endAngle: number;
67
+ color?: string;
68
+ opacity?: number;
69
+ gradient?: SectorScanGradientOptions;
70
+ outlineColor?: string;
71
+ outlineOpacity?: number;
72
+ outlineWidth?: number;
73
+ rotationSpeed?: number;
74
+ }
75
+ /** 定向脉冲:一组沿指定方向推进的弧线。 */
76
+ export interface DirectionalPulseOptions extends BaseEffectOptions {
77
+ radius: number;
78
+ direction?: number;
79
+ spread?: number;
80
+ color?: string;
81
+ opacity?: number;
82
+ lineWidth?: number;
83
+ lineCount?: number;
84
+ lineSpacing?: number;
85
+ speed?: number;
86
+ innerRadius?: number;
87
+ }
88
+ /** 雷达扫描:距离环、十字线、距离文字和旋转扫描尾迹。 */
89
+ export interface RadarSweepOptions extends BaseEffectOptions {
90
+ radius: number;
91
+ color?: string;
92
+ opacity?: number;
93
+ sweepAngle?: number;
94
+ sweepStartAngle?: number;
95
+ rotationSpeed?: number;
96
+ ringCount?: number;
97
+ ringColor?: string;
98
+ ringOpacity?: number;
99
+ ringWidth?: number;
100
+ trailCount?: number;
101
+ tailOpacity?: number;
102
+ headOpacity?: number;
103
+ showCrosshair?: boolean;
104
+ crosshairColor?: string;
105
+ crosshairOpacity?: number;
106
+ crosshairWidth?: number;
107
+ coreRadius?: number;
108
+ coreColor?: string;
109
+ showDistanceLabels?: boolean;
110
+ distanceLabelColor?: string;
111
+ distanceLabelHaloColor?: string;
112
+ distanceLabelOpacity?: number;
113
+ distanceLabelSize?: number;
114
+ distanceLabelFormatter?: (distance: number, index: number) => string;
115
+ }
116
+ /** 添加单点扩散脉冲特效。 */
117
+ export declare const addPulseMarker: (map: Map, options: PulseMarkerOptions) => MapEffectController<PulseMarkerOptions>;
118
+ /** 添加多环脉冲特效。 */
119
+ export declare const addRingPulseMarker: (map: Map, options: RingPulseMarkerOptions) => MapEffectController<RingPulseMarkerOptions>;
120
+ /** 添加扇形扫描特效。 */
121
+ export declare const addSectorScan: (map: Map, options: SectorScanOptions) => MapEffectController<SectorScanOptions>;
122
+ /** 添加定向脉冲特效。 */
123
+ export declare const addDirectionalPulse: (map: Map, options: DirectionalPulseOptions) => MapEffectController<DirectionalPulseOptions>;
124
+ /** 添加雷达扫描特效。 */
125
+ export declare const addRadarSweep: (map: Map, options: RadarSweepOptions) => MapEffectController<RadarSweepOptions>;
126
+ export {};
@@ -0,0 +1,9 @@
1
+ export { getMaplibreToolsConfig, setMaplibreToolsConfig } from "./config";
2
+ export type { MaplibreToolsConfig } from "./config";
3
+ export { BASE_MAP_TYPES, getBaseMapStyle, getOpenFreeMapStyle, OPENFREEMAP_STYLE_BASE_URL, OPENFREEMAP_STYLES, OPENFREEMAP_STYLE_TYPES, isBaseMapType, setBaseMap, TDT_STYLE_TYPES, createTiandituImageStyle, createTiandituRasterSource, } from "./basemaps";
4
+ export type { BaseMapOptions, BaseMapType, OpenFreeMapStyleConfig, OpenFreeMapStyleType, TiandituLayerType, TiandituOptions, TiandituStyleOptions, } from "./basemaps";
5
+ export { addDirectionalPulse, addPulseMarker, addRingPulseMarker, addRadarSweep, addSectorScan, } from "./effects";
6
+ export type { DirectionalPulseOptions, MapEffectController, PulseMarkerOptions, RingPulseMarkerOptions, RadarSweepOptions, SectorScanOptions, } from "./effects";
7
+ export { createMap, maplibregl } from "./map";
8
+ export type { CreateMapOptions } from "./map";
9
+ export type { GeoJSONSourceSpecification, LayerSpecification, Map, MapOptions, RasterSourceSpecification, SourceSpecification, StyleSpecification, } from "maplibre-gl";
@@ -0,0 +1,11 @@
1
+ import maplibregl, { type Map, type MapOptions, type StyleSpecification } from "maplibre-gl";
2
+ import { type BaseMapType } from "../basemaps";
3
+ export interface CreateMapOptions extends Omit<MapOptions, "container" | "style"> {
4
+ container: string | HTMLElement;
5
+ /** 可传内置底图类型,也可直接传 MapLibre style URL 或 StyleSpecification。 */
6
+ style?: BaseMapType | string | StyleSpecification;
7
+ /** 只在使用天地图底图时需要;优先级高于全局配置。 */
8
+ tdtToken?: string;
9
+ }
10
+ export declare const createMap: (options: CreateMapOptions) => Map;
11
+ export { maplibregl };
@@ -0,0 +1,2 @@
1
+ export { createMap, maplibregl } from "./create-map";
2
+ export type { CreateMapOptions } from "./create-map";
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@bitalltech-maplibre/core",
3
+ "version": "1.0.0",
4
+ "description": "BitAllTech MapLibre 业务组件核心包",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "unpkg": "dist/index.umd.js",
8
+ "types": "dist/types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types/index.d.ts",
12
+ "import": "./dist/index.esm.js",
13
+ "require": "./dist/index.cjs.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist/"
18
+ ],
19
+ "scripts": {
20
+ "dev": "vite build --watch",
21
+ "build": "vite build && tsc --project tsconfig.json --emitDeclarationOnly",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "bitalltech",
26
+ "maplibre",
27
+ "core"
28
+ ],
29
+ "license": "UNLICENSED",
30
+ "sideEffects": false,
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "peerDependencies": {
35
+ "maplibre-gl": "^5.24.0"
36
+ }
37
+ }