aviation-chart 0.3.25 → 2.0.1

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.
@@ -3463,7 +3463,10 @@ class GlobalConfigManager {
3463
3463
  const headers = this.config.apiKey
3464
3464
  ? { "X-Api-Key": this.config.apiKey }
3465
3465
  : {};
3466
- const response = await fetch(`${base}/api/periods`, { headers });
3466
+ const apiPath = this.config.apiVersion
3467
+ ? `${base}/api/${this.config.apiVersion}/periods`
3468
+ : `${base}/api/periods`;
3469
+ const response = await fetch(apiPath, { headers });
3467
3470
  if (!response.ok) {
3468
3471
  throw new Error(`获取期数失败(${response.status})`);
3469
3472
  }
@@ -4286,6 +4289,10 @@ class GraticuleManager {
4286
4289
  function authHeaders(apiKey) {
4287
4290
  return apiKey ? { "X-Api-Key": apiKey } : {};
4288
4291
  }
4292
+ function apiPrefix$1(baseUrl, version) {
4293
+ const base = baseUrl.replace(/\/$/, "");
4294
+ return version ? `${base}/api/${version}` : `${base}/api`;
4295
+ }
4289
4296
  async function toJSON(res) {
4290
4297
  if (!res.ok) {
4291
4298
  let detail = "";
@@ -4301,7 +4308,7 @@ async function toJSON(res) {
4301
4308
  }
4302
4309
  return res.json();
4303
4310
  }
4304
- async function searchFeatures(baseUrl, apiKey, params) {
4311
+ async function searchFeatures(baseUrl, apiKey, params, version) {
4305
4312
  const { q, type, period, limit, signal } = params;
4306
4313
  if (!q || !q.trim()) {
4307
4314
  throw new Error("search: q 参数必填");
@@ -4313,7 +4320,7 @@ async function searchFeatures(baseUrl, apiKey, params) {
4313
4320
  qs.set("period", period);
4314
4321
  if (limit != null)
4315
4322
  qs.set("limit", String(limit));
4316
- const res = await fetch(`${baseUrl}/api/search?${qs.toString()}`, {
4323
+ const res = await fetch(`${apiPrefix$1(baseUrl, version)}/search?${qs.toString()}`, {
4317
4324
  method: "GET",
4318
4325
  headers: authHeaders(apiKey),
4319
4326
  ...(signal ? { signal } : {}),
@@ -4321,7 +4328,7 @@ async function searchFeatures(baseUrl, apiKey, params) {
4321
4328
  const data = await toJSON(res);
4322
4329
  return data.results ?? [];
4323
4330
  }
4324
- async function getFeatureGeometry(baseUrl, apiKey, params) {
4331
+ async function getFeatureGeometry(baseUrl, apiKey, params, version) {
4325
4332
  const { type, id, period, signal } = params;
4326
4333
  if (!type || !id) {
4327
4334
  throw new Error("getGeometry: type 和 id 参数必填");
@@ -4329,15 +4336,15 @@ async function getFeatureGeometry(baseUrl, apiKey, params) {
4329
4336
  const qs = new URLSearchParams({ type, id });
4330
4337
  if (period)
4331
4338
  qs.set("period", period);
4332
- const res = await fetch(`${baseUrl}/api/geometry?${qs.toString()}`, {
4339
+ const res = await fetch(`${apiPrefix$1(baseUrl, version)}/geometry?${qs.toString()}`, {
4333
4340
  method: "GET",
4334
4341
  headers: authHeaders(apiKey),
4335
4342
  ...(signal ? { signal } : {}),
4336
4343
  });
4337
4344
  return toJSON(res);
4338
4345
  }
4339
- async function getPeriods(baseUrl, apiKey, signal) {
4340
- const res = await fetch(`${baseUrl}/api/periods`, {
4346
+ async function getPeriods(baseUrl, apiKey, signal, version) {
4347
+ const res = await fetch(`${apiPrefix$1(baseUrl, version)}/periods`, {
4341
4348
  method: "GET",
4342
4349
  headers: authHeaders(apiKey),
4343
4350
  ...(signal ? { signal } : {}),
@@ -7405,6 +7412,10 @@ return exported;
7405
7412
  var mlcontour$1 = mlcontour;
7406
7413
 
7407
7414
  const DEFAULT_CHART_API_URL = "https://aips.siniswift.com";
7415
+ function apiPrefix(apiUrl, version) {
7416
+ const base = apiUrl.replace(/\/$/, "");
7417
+ return version ? `${base}/api/${version}` : `${base}/api`;
7418
+ }
7408
7419
  function getAviationBaseStyle(opts) {
7409
7420
  const apiUrl = opts.apiUrl.replace(/\/$/, "");
7410
7421
  const spriteBase = (opts.spriteUrl ?? apiUrl).replace(/\/$/, "");
@@ -7436,21 +7447,21 @@ function getAviationBaseStyle(opts) {
7436
7447
  }
7437
7448
  };
7438
7449
  }
7439
- function navdataTilesUrl(apiUrl, period) {
7440
- return `${apiUrl.replace(/\/$/, "")}/api/tiles/${period}/{z}/{x}/{y}.pbf`;
7450
+ function navdataTilesUrl(apiUrl, period, version) {
7451
+ return `${apiPrefix(apiUrl, version)}/tiles/${period}/{z}/{x}/{y}.pbf`;
7441
7452
  }
7442
- function getNavdataSource(apiUrl, period) {
7453
+ function getNavdataSource(apiUrl, period, version) {
7443
7454
  return {
7444
7455
  type: "vector",
7445
- tiles: [navdataTilesUrl(apiUrl, period)],
7456
+ tiles: [navdataTilesUrl(apiUrl, period, version)],
7446
7457
  minzoom: 0.5,
7447
7458
  maxzoom: 18,
7448
7459
  };
7449
7460
  }
7450
- function getChartAmmSource(apiUrl) {
7461
+ function getChartAmmSource(apiUrl, version) {
7451
7462
  return {
7452
7463
  type: "vector",
7453
- tiles: [`${apiUrl.replace(/\/$/, "")}/api/amm/{z}/{x}/{y}.pbf`],
7464
+ tiles: [`${apiPrefix(apiUrl, version)}/amm/{z}/{x}/{y}.pbf`],
7454
7465
  minzoom: 11,
7455
7466
  maxzoom: 18,
7456
7467
  };
@@ -7581,103 +7592,216 @@ async function fetchGzJson(url, headers = {}) {
7581
7592
  return new Response(stream).json();
7582
7593
  }
7583
7594
 
7584
- // ICAO aviation chart layer styles — multi-theme support.
7585
- // Add new themes by implementing buildLayersXxx() and registering in CHART_THEMES.
7595
+ // ICAO aviation chart layer styles — token-driven multi-theme.
7596
+ //
7597
+ // 单一 buildLayers(T):图层结构只写一份(以 light 为准);凡随主题变化的值
7598
+ // (颜色 / halo / icon-image / pattern)都从 token 表 T 取。尺寸曲线、zoom、
7599
+ // 偏移、opacity 曲线、text-field、placement 等结构性属性两主题一致,写死。
7600
+ //
7601
+ // 加主题 = 在 THEME_TOKENS 增加一张 token 表;不再复制整份 build 函数,
7602
+ // 彻底消除 light/dark 漂移(历史上 dark 航线消失、6,6 插值等 bug 均源于此)。
7603
+ //
7604
+ // 本次新增两套主题:
7605
+ // dusk 暮光模式 —— 晨昏蒙影时段过渡用,中等亮度,避免日/夜切换的瞳孔冲击
7606
+ // redNight 红光夜视模式 —— 驾驶舱标准红光照明,全色系统一为红色,
7607
+ // 靠明度而非色相区分要素,保护夜间暗适应(视杆细胞)
7586
7608
 
7587
- // ── Light theme ───────────────────────────────────────────────────────────────
7588
- // const ICAO_LIGHT = {
7589
- // airspaceStroke: '#AAB7B8',
7590
- // restrictedStroke: "#D35400",
7591
- // controlledStroke: '#6ec1f4',
7592
- // controlledFill: '#6ec1f4',
7593
- // segment: '#0044AA',
7594
- // waypoint: '#663399',
7595
- // vor: '#00008B',
7596
- // ndb: '#0066CC',
7597
- // airport: '#CC6600',
7598
- // runway: '#333333',
7599
- // }
7600
- const ICAO_LIGHT = {
7601
- airspaceStroke: '#AAB7B8',
7602
- restrictedStroke: "#D35400",
7603
- controlledStroke: '#10B981',
7604
- controlledFill: '#10B981',
7605
- segment: '#2E4053',
7606
- waypoint: '#1C2526',
7607
- vor: '#00008B',
7608
- ndb: '#0066CC',
7609
- airport: '#006400',
7610
- runway: '#333333',
7609
+ /**
7610
+ * 主题 token 表。每个 key 是一个"随主题变化"的值,值可以是颜色字符串、
7611
+ * _ml 表达式,或 halo 片段对象(用对象展开有条件地注入 text-halo-*)。
7612
+ */
7613
+ const THEME_TOKENS = {
7614
+ light: {
7615
+ background: '#EAF2F8',
7616
+ land: '#F7F9FB',
7617
+ halo: '#ffffff',
7618
+ boundaryPattern: 'normal:national-border',
7619
+ adizLine: null, // light 不给 adiz 线描色(仅用 pattern)
7620
+ adizLabel: '#6600cc',
7621
+ airspaceStroke: '#AAB7B8',
7622
+ restrictedFill: '#FAD7A0',
7623
+ restrictedStrokeLine: '#f6bf65',
7624
+ restrictedStroke: '#D35400', // 限制区标注文字色(ICAO 导出/图例用)
7625
+ controlledStroke: '#10B981',
7626
+ controlledFill: '#10B981',
7627
+ segment: '#2E4053',
7628
+ segmentRemark: '#E8A020', // HAS_REMARK 航段
7629
+ airport: '#006400', // 机场图标色
7630
+ airportText: '#006400', // 机场文字色(非 AMM)
7631
+ runway: '#333333',
7632
+ vorDial: '#0b417a',
7633
+ vorNormal: '#3874cb',
7634
+ vor: '#00008B',
7635
+ ndbIcon: 'v2:ndb-normal', // 图标按主题不同(正常)
7636
+ ndb: '#0066CC',
7637
+ waypoint: '#1C2526',
7638
+ // airline_label format 内嵌文字色
7639
+ alBase: '#ffffff', alDist: '#3E4759', alRnp: '#E8A020',
7640
+ // halo 片段:light 多数标注无 halo → 空对象
7641
+ sideHalo: {},
7642
+ centerHalo: {},
7643
+ restrictedHalo: {},
7644
+ controlledHalo: {},
7645
+ radialHalo: {},
7646
+ runwayHalo: { 'text-halo-width': 1 },
7647
+ alHalo: { 'text-halo-color': '#ffffff', 'text-halo-width': 0.1 },
7648
+ ndbHalo: { 'text-halo-color': '#ffffff', 'text-halo-width': 0.5, 'text-halo-blur': 1 },
7649
+ },
7650
+ dark: {
7651
+ background: '#000000',
7652
+ land: '#0A111A',
7653
+ halo: '#0f172a',
7654
+ boundaryPattern: 'normal:national-border-dark',
7655
+ adizLine: '#a855f7',
7656
+ adizLabel: '#c084fc',
7657
+ airspaceStroke: '#18C29C',
7658
+ restrictedFill: ['case', ['==', ['get', 'CODE_TYPE'], 'P'], '#ef4444', ['==', ['get', 'CODE_TYPE'], 'D'], '#f97316', '#ef4444'],
7659
+ restrictedStrokeLine: '#CC7722',
7660
+ restrictedStroke: '#CC7722',
7661
+ controlledStroke: '#22C55E',
7662
+ controlledFill: '#22C55E',
7663
+ segment: '#40C4FF',
7664
+ segmentRemark: '#fbbf24',
7665
+ airport: '#73ccdd',
7666
+ airportText: '#E0F7FA',
7667
+ runway: '#64748b',
7668
+ vorDial: '#38bdf8',
7669
+ vorNormal: '#38bdf8',
7670
+ vor: '#72aae5',
7671
+ ndbIcon: 'ndb-inway',
7672
+ ndb: '#62d6ef',
7673
+ waypoint: '#74cdde',
7674
+ alBase: '#0f172a', alDist: '#cbd5e1', alRnp: '#FFFFFF',
7675
+ sideHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
7676
+ centerHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1.5 },
7677
+ restrictedHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
7678
+ controlledHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1.5 },
7679
+ radialHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
7680
+ runwayHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
7681
+ alHalo: {},
7682
+ ndbHalo: { 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
7683
+ },
7684
+ // ── 新增:暮光模式(晨昏蒙影 / 日夜切换过渡)───────────────────────────
7685
+ // 设计目标:亮度介于 light 与 dark 之间,避免瞳孔在两个极端间来回收放;
7686
+ // 色相仍按 light 的语义分组(橙=限制区/绿=管制区),但饱和度、对比度降低。
7687
+ dusk: {
7688
+ background: '#1B2838',
7689
+ land: '#22303F',
7690
+ halo: '#16212c',
7691
+ boundaryPattern: 'normal:national-border-dark', // 复用 dark 的深色底图案
7692
+ adizLine: '#c77dff',
7693
+ adizLabel: '#e0aaff',
7694
+ airspaceStroke: '#7fb3d5',
7695
+ restrictedFill: '#e67e22',
7696
+ restrictedStrokeLine: '#e59866',
7697
+ restrictedStroke: '#e59866',
7698
+ controlledStroke: '#52c9a3',
7699
+ controlledFill: '#52c9a3',
7700
+ segment: '#8fa8c7',
7701
+ segmentRemark: '#f4c542',
7702
+ airport: '#7fd1ae',
7703
+ airportText: '#dce9f0',
7704
+ runway: '#7c8ea3',
7705
+ vorDial: '#5dade2',
7706
+ vorNormal: '#5dade2',
7707
+ vor: '#85a9e0',
7708
+ ndbIcon: 'ndb-inway',
7709
+ ndb: '#7ec8e3',
7710
+ waypoint: '#a9c6d8',
7711
+ alBase: '#1B2838', alDist: '#b8c9d9', alRnp: '#f4c542',
7712
+ sideHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1 },
7713
+ centerHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1.5 },
7714
+ restrictedHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1 },
7715
+ controlledHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1.5 },
7716
+ radialHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1 },
7717
+ runwayHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1 },
7718
+ alHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 0.5 },
7719
+ ndbHalo: { 'text-halo-color': '#1B2838', 'text-halo-width': 1 },
7720
+ },
7721
+ // ── 新增:ForeFlight 风格(致敬,非像素级复刻,官方未公开具体色值)──────
7722
+ // 设计目标:暖米黄底图 + 扁平化(去地形纹理)+ 传统航图色彩语义
7723
+ // (蓝=管制空域,洋红=非管制机场,棕=NDB,橙=限制区)+ 现代无衬线字体,
7724
+ // 整体比三色 VFR 纸图更"干净",符合 ForeFlight 网页版/Light 主题的视觉语言。
7725
+ foreflight: {
7726
+ background: '#F2EFE6',
7727
+ land: '#F7F5EC',
7728
+ halo: '#F2EFE6',
7729
+ boundaryPattern: 'normal:national-border',
7730
+ adizLine: '#8e44ad',
7731
+ adizLabel: '#8e44ad',
7732
+ airspaceStroke: '#2E5C8A',
7733
+ restrictedFill: '#E8A33D',
7734
+ restrictedStrokeLine: '#C0392B',
7735
+ restrictedStroke: '#C0392B',
7736
+ controlledStroke: '#2E5C8A',
7737
+ controlledFill: '#2E5C8A',
7738
+ segment: '#34495E',
7739
+ segmentRemark: '#D68910',
7740
+ airport: '#B03060',
7741
+ airportText: '#1B2631',
7742
+ runway: '#4A4A4A',
7743
+ vorDial: '#2E5C8A',
7744
+ vorNormal: '#2E5C8A',
7745
+ vor: '#154360',
7746
+ ndbIcon: 'v2:ndb-normal',
7747
+ ndb: '#8B5A2B',
7748
+ waypoint: '#2C3E50',
7749
+ alBase: '#F2EFE6', alDist: '#5D6D7E', alRnp: '#D68910',
7750
+ sideHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1 },
7751
+ centerHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1.5 },
7752
+ restrictedHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1 },
7753
+ controlledHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1.5 },
7754
+ radialHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1 },
7755
+ runwayHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1 },
7756
+ alHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 0.5 },
7757
+ ndbHalo: { 'text-halo-color': '#F2EFE6', 'text-halo-width': 1 },
7758
+ },
7611
7759
  };
7612
7760
 
7613
- function buildLayersLight() {
7761
+ function buildLayers(themeId = 'light') {
7762
+ const T = THEME_TOKENS[themeId] ?? THEME_TOKENS.light;
7614
7763
  const sourceId = 'navdata';
7615
- const C = ICAO_LIGHT;
7616
7764
  return [
7617
7765
  {
7618
7766
  "id": "landLayer", "type": "fill", "source": "land",
7619
7767
  "layout": { "visibility": "visible" },
7620
- "paint": { "fill-color": "#F7F9FB", "fill-opacity": 1 }
7768
+ "paint": { "fill-color": T.land, "fill-opacity": 1 }
7621
7769
  },
7622
7770
  {
7623
- "id": "boundary",
7624
- "type": "line",
7625
- "source": "boundary",
7626
- "minzoom": 0,
7771
+ "id": "boundary", "type": "line", "source": "boundary", "minzoom": 0,
7627
7772
  "paint": {
7628
- "line-width": [
7629
- "interpolate",
7630
- [
7631
- "linear"
7632
- ],
7633
- [
7634
- "zoom"
7635
- ],
7636
- 0,
7637
- 1,
7638
- 7,
7639
- 4
7640
- ],
7641
- "line-opacity": [
7642
- "interpolate",
7643
- [
7644
- "linear"
7645
- ],
7646
- [
7647
- "zoom"
7648
- ],
7649
- 0,
7650
- 1,
7651
- 2,
7652
- 0.5
7653
- ],
7654
- "line-pattern": "normal:national-border"
7773
+ "line-width": ["interpolate", ["linear"], ["zoom"], 0, 1, 7, 4],
7774
+ "line-opacity": ["interpolate", ["linear"], ["zoom"], 0, 1, 2, 0.5],
7775
+ "line-pattern": T.boundaryPattern,
7655
7776
  }
7656
7777
  },
7657
7778
  {
7658
7779
  id: 'adiz-line', type: 'line', source: sourceId, 'source-layer': 'adiz', minzoom: 3,
7659
7780
  layout: { 'line-cap': 'round', 'line-join': 'round' },
7660
- paint: { 'line-width': 4, "line-pattern": "normal:adiz", 'line-opacity': ['interpolate', ['linear'], ['zoom'], 3, 0.6, 8, 0.4] },
7781
+ paint: {
7782
+ ...(T.adizLine ? { 'line-color': T.adizLine } : {}),
7783
+ 'line-width': 4, "line-pattern": "normal:adiz",
7784
+ 'line-opacity': ['interpolate', ['linear'], ['zoom'], 3, 0.6, 8, 0.4],
7785
+ },
7661
7786
  },
7662
7787
  {
7663
7788
  id: 'adiz-label', type: 'symbol', source: sourceId, 'source-layer': 'adiz-centroid', minzoom: 3,
7664
7789
  layout: { 'text-field': ['coalesce', ['get', 'TXT_NAME'], ['get', 'CODE_ID']], 'text-size': 10, 'text-max-width': 10, 'symbol-placement': 'point' },
7665
- paint: { 'text-color': '#6600cc', 'text-halo-color': '#ffffff', 'text-halo-width': 1.5 },
7790
+ paint: { 'text-color': T.adizLabel, 'text-halo-color': T.halo, 'text-halo-width': 1.5 },
7666
7791
  },
7667
7792
  {
7668
7793
  id: 'airspaceLayer', type: 'line', source: sourceId, 'source-layer': 'fir', minzoom: 2,
7669
- // layout: { "line-cap": "butt", "line-join": "miter", "line-miter-limit": 0 },
7670
- paint: { "line-color": C.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 2, 0, 2.7, 0.8, 9, 0.8, 10, 0.5], "line-width": 0.5, 'line-dasharray': [4.2, 4] }
7794
+ paint: { "line-color": T.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 2, 0, 2.7, 0.8, 9, 0.8, 10, 0.5], "line-width": 0.5, 'line-dasharray': [4.2, 4] }
7671
7795
  },
7672
7796
  {
7673
7797
  "id": "airspaceLayer_line", type: 'line', source: sourceId, 'source-layer': 'fir', "minzoom": 5,
7674
7798
  layout: { "line-miter-limit": 0, "line-cap": "butt", "line-join": "miter" },
7675
- paint: { "line-color": C.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 5, 0, 5.5, 0.8, 9, 0.8, 10, 0.5], "line-width": 6, "line-dasharray": [0.2, 5] }
7799
+ paint: { "line-color": T.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 5, 0, 5.5, 0.8, 9, 0.8, 10, 0.5], "line-width": 6, "line-dasharray": [0.2, 5] }
7676
7800
  },
7677
7801
  {
7678
7802
  id: 'airspace_label_side_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir', minzoom: 4,
7679
7803
  layout: { 'text-field': ["concat", ["get", "TXT_NAME"], "/", ["get", "CODE_ID"], "/", ["get", "CODE_TYPE"]], 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1], "text-letter-spacing": 0.05, "text-optional": true },
7680
- paint: { 'text-color': C.airspaceStroke },
7804
+ paint: { 'text-color': T.airspaceStroke, ...T.sideHalo },
7681
7805
  },
7682
7806
  {
7683
7807
  id: 'airspace_label_center_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir-centroid', minzoom: 3,
@@ -7688,98 +7812,50 @@ function buildLayersLight() {
7688
7812
  'text-max-width': 8,
7689
7813
  },
7690
7814
  paint: {
7691
- 'text-color': C.airspaceStroke,
7815
+ 'text-color': T.airspaceStroke,
7816
+ ...T.centerHalo,
7692
7817
  'text-opacity': ['interpolate', ['linear'], ['zoom'], 3, 0.85, 8, 0.7, 12, 0.5],
7693
7818
  },
7694
7819
  },
7695
7820
  {
7696
7821
  id: 'restrictedLayer', type: 'fill', source: sourceId, 'source-layer': 'restricted-fill', minzoom: 4,
7697
7822
  paint: {
7698
- 'fill-color': "#FAD7A0",
7699
- // "fill-pattern": "normal:passline",
7700
- 'fill-opacity': [
7701
- "interpolate",
7702
- [
7703
- "linear"
7704
- ],
7705
- [
7706
- "zoom"
7707
- ],
7708
- 10,
7709
- 0.15,
7710
- 11.5,
7711
- 0
7712
- ],
7823
+ 'fill-color': T.restrictedFill,
7824
+ 'fill-opacity': ["interpolate", ["linear"], ["zoom"], 10, 0.15, 11.5, 0],
7713
7825
  },
7714
7826
  },
7715
7827
  {
7716
7828
  id: 'restrictedLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'restricted',
7717
- paint: { 'line-color': "#f6bf65", 'line-width': 1, "line-dasharray": [2, 2], "line-opacity": ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1] },
7829
+ paint: { 'line-color': T.restrictedStrokeLine, 'line-width': 1, "line-dasharray": [2, 2], "line-opacity": ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1] },
7718
7830
  },
7719
7831
  {
7720
7832
  id: 'restricted_line_label', type: 'symbol', source: sourceId, 'source-layer': 'restricted', minzoom: 6,
7721
7833
  layout: { 'text-field': ["concat", ["get", "TXT_NAME"], "/", ["get", "CODE_ID"], "/", ["get", "CODE_TYPE"]], "text-letter-spacing": 0.1, 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1] },
7722
- paint: { 'text-color': C.restrictedStroke },
7834
+ paint: { 'text-color': T.restrictedStroke, ...T.restrictedHalo },
7723
7835
  },
7724
7836
  {
7725
7837
  id: 'controlledLayer', type: 'fill', source: sourceId, 'source-layer': 'controlled-fill', minzoom: 4,
7726
7838
  paint: {
7727
- 'fill-color': C.controlledFill,
7728
- "fill-opacity": [
7729
- "interpolate",
7730
- [
7731
- "linear"
7732
- ],
7733
- [
7734
- "zoom"
7735
- ],
7736
- 10,
7737
- 0.035,
7738
- 11.5,
7739
- 0
7740
- ]
7839
+ 'fill-color': T.controlledFill,
7840
+ "fill-opacity": ["interpolate", ["linear"], ["zoom"], 10, 0.035, 11.5, 0],
7741
7841
  },
7742
7842
  },
7743
7843
  {
7744
7844
  id: 'controlledLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'controlled',
7745
-
7746
- paint: {
7747
- 'line-color': C.controlledStroke, 'line-width': 1, 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1], "line-dasharray": [1,
7748
- 1.4]
7749
- },
7845
+ paint: { 'line-color': T.controlledStroke, 'line-width': 1, 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1], "line-dasharray": [1, 1.4] },
7750
7846
  },
7751
7847
  {
7752
- id: 'controlled_line_label',
7753
- type: 'symbol', source: sourceId, 'source-layer': 'controlled', minzoom: 6,
7848
+ id: 'controlled_line_label', type: 'symbol', source: sourceId, 'source-layer': 'controlled', minzoom: 6,
7754
7849
  layout: { 'text-field': ["concat", ["get", "TXT_NAME"], "/", ["get", "CODE_ID"], "/", ["get", "CODE_TYPE"]], 'text-size': 10, 'symbol-placement': 'line', 'text-letter-spacing': 0.2, 'text-max-width': 8, "text-offset": [0, 1] },
7755
- paint: { 'text-color': C.controlledStroke },
7850
+ paint: { 'text-color': T.controlledStroke, ...T.controlledHalo },
7756
7851
  },
7757
7852
  {
7758
7853
  id: 'airline', type: 'line', source: sourceId, 'source-layer': 'segment', minzoom: 6,
7759
7854
  paint: {
7760
- 'line-color': ['case', ['==', ['get', 'HAS_REMARK'], 1], '#E8A020', C.segment],
7855
+ 'line-color': ['case', ['==', ['get', 'HAS_REMARK'], 1], T.segmentRemark, T.segment],
7761
7856
  'line-width': ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
7762
7857
  "line-blur": 0,
7763
- "line-opacity":
7764
- [
7765
- "interpolate",
7766
- [
7767
- "linear"
7768
- ],
7769
- [
7770
- "zoom"
7771
- ],
7772
- 6,
7773
- 0.3,
7774
- 7,
7775
- 1,
7776
- 8,
7777
- 1,
7778
- 12,
7779
- 0.8,
7780
- 15,
7781
- 0.2
7782
- ]
7858
+ "line-opacity": ["interpolate", ["linear"], ["zoom"], 6, 0.3, 7, 1, 8, 1, 12, 0.8, 15, 0.2],
7783
7859
  }
7784
7860
  },
7785
7861
  {
@@ -7790,56 +7866,27 @@ function buildLayersLight() {
7790
7866
  "text-allow-overlap": false, "icon-allow-overlap": false, "text-optional": false,
7791
7867
  "text-anchor": "center", "text-justify": "center", "text-line-height": 1.3, "text-letter-spacing": 0.1,
7792
7868
  "text-field": ["step", ["zoom"],
7793
- ["format", ["case", ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": "#ffffff" }],
7869
+ ["format", ["case", ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": T.alBase }],
7794
7870
  10,
7795
7871
  ["format",
7796
- ["concat", ["get", "VAL_LEN"], "", ["get", "UOM_DIST"]], { "font-scale": 0.95, "text-color": "#3E4759" }, "\n",
7797
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""], ""], { "font-scale": 1, "text-color": "#E8A020" },
7872
+ ["concat", ["get", "VAL_LEN"], "", ["get", "UOM_DIST"]], { "font-scale": 0.95, "text-color": T.alDist }, "\n",
7873
+ ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""], ""], { "font-scale": 1, "text-color": T.alRnp },
7798
7874
  ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], " ", ""], ""], {},
7799
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": "#ffffff", "font-weight": "bold" },
7875
+ ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": T.alBase, "font-weight": "bold" },
7800
7876
  ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], "", ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], " ", ""]], {},
7801
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], "", ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""]], { "font-scale": 0.85, "text-color": "#E8A020" },
7877
+ ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], "", ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""]], { "font-scale": 0.85, "text-color": T.alRnp },
7802
7878
  "\n",
7803
- ["case", ["all", ["has", "TXT_DESIG_HIGH"], ["!=", ["get", "TXT_DESIG_HIGH"], ""]], ["get", "TXT_DESIG_HIGH"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 0.95, "text-color": "#3E4759" }
7879
+ ["case", ["all", ["has", "TXT_DESIG_HIGH"], ["!=", ["get", "TXT_DESIG_HIGH"], ""]], ["get", "TXT_DESIG_HIGH"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 0.95, "text-color": T.alDist }
7804
7880
  ]
7805
7881
  ],
7806
7882
  "text-size": ["interpolate", ["linear"], ["zoom"], 6, 9, 10, 10],
7807
7883
  "icon-text-fit-padding": [0, 3, 0, 3],
7808
7884
  },
7809
7885
  paint: {
7810
- "text-halo-color": "#ffffff",
7811
- "text-halo-width": 0.1,
7812
- "icon-color": C.segment,
7813
- "text-opacity": [
7814
- "interpolate",
7815
- [
7816
- "linear"
7817
- ],
7818
- [
7819
- "zoom"
7820
- ],
7821
- 6,
7822
- 1,
7823
- 12,
7824
- 1,
7825
- 15,
7826
- 0.3
7827
- ],
7828
- "icon-opacity": [
7829
- "interpolate",
7830
- [
7831
- "linear"
7832
- ],
7833
- [
7834
- "zoom"
7835
- ],
7836
- 6,
7837
- 1,
7838
- 12,
7839
- 1,
7840
- 15,
7841
- 0.3
7842
- ]
7886
+ ...T.alHalo,
7887
+ "icon-color": T.segment,
7888
+ "text-opacity": ["interpolate", ["linear"], ["zoom"], 6, 1, 12, 1, 15, 0.3],
7889
+ "icon-opacity": ["interpolate", ["linear"], ["zoom"], 6, 1, 12, 1, 15, 0.3],
7843
7890
  },
7844
7891
  },
7845
7892
  {
@@ -7854,7 +7901,7 @@ function buildLayersLight() {
7854
7901
  'text-offset': [0, -0.6],
7855
7902
  'text-justify': 'auto',
7856
7903
  },
7857
- paint: { 'text-color': C.segment },
7904
+ paint: { 'text-color': T.segment, ...T.radialHalo },
7858
7905
  },
7859
7906
  {
7860
7907
  id: 'airport', type: 'symbol', source: sourceId, minzoom: 3, 'source-layer': 'airport',
@@ -7877,102 +7924,34 @@ function buildLayersLight() {
7877
7924
  "text-allow-overlap": true,
7878
7925
  "text-ignore-placement": true,
7879
7926
  "visibility": "none",
7880
- "icon-size": [
7881
- "interpolate",
7882
- [
7883
- "linear"
7884
- ],
7885
- [
7886
- "zoom"
7887
- ],
7888
- 5,
7889
- 0.6,
7890
- 9,
7891
- 1.2,
7892
- 12,
7893
- 1.3
7894
- ]
7927
+ "icon-size": ["interpolate", ["linear"], ["zoom"], 5, 0.6, 9, 1.2, 12, 1.3]
7895
7928
  },
7896
7929
  paint: {
7897
- 'icon-color': ['case',
7898
- ['has', 'has_amm'], '#4B2D6E',
7899
- C.airport,
7900
- ],
7901
- "icon-opacity": [
7902
- "interpolate",
7903
- [
7904
- "linear"
7905
- ],
7906
- [
7907
- "zoom"
7908
- ],
7909
- 2,
7910
- 0.75,
7911
- 3,
7912
- 0.95,
7913
- 5,
7914
- 1,
7915
- 9,
7916
- 1,
7917
- 11,
7918
- 0.2
7919
- ],
7920
- "text-color": ['case',
7921
- ['has', 'has_amm'], '#4B2D6E',
7922
- C.airport,
7923
- ],
7924
- "text-opacity": [
7925
- "interpolate",
7926
- [
7927
- "linear"
7928
- ],
7929
- [
7930
- "zoom"
7931
- ],
7932
- 4,
7933
- 0.95,
7934
- 5,
7935
- 1,
7936
- 9,
7937
- 1,
7938
- 11,
7939
- 0.2
7940
- ],
7930
+ 'icon-color': ['case', ['has', 'has_amm'], '#4B2D6E', T.airport],
7931
+ "icon-opacity": ["interpolate", ["linear"], ["zoom"], 2, 0.75, 3, 0.95, 5, 1, 9, 1, 11, 0.2],
7932
+ "text-color": ['case', ['has', 'has_amm'], '#4B2D6E', T.airportText],
7933
+ "text-opacity": ["interpolate", ["linear"], ["zoom"], 4, 0.95, 5, 1, 9, 1, 11, 0.2],
7941
7934
  },
7942
7935
  },
7943
7936
  {
7944
- id: 'runway-line',
7945
- type: 'line',
7946
- source: sourceId,
7947
- 'source-layer': 'runway',
7948
- filter: ['!', ['has', 'has_amm']],
7949
- minzoom: 4,
7950
- maxzoom: 11,
7937
+ id: 'runway-line', type: 'line', source: sourceId, 'source-layer': 'runway',
7938
+ filter: ['!', ['has', 'has_amm']], minzoom: 4, maxzoom: 11,
7951
7939
  paint: {
7952
- 'line-color': C.runway,
7940
+ 'line-color': T.runway,
7953
7941
  'line-width': ['interpolate', ['linear'], ['zoom'], 4, 1, 13, 10],
7954
7942
  },
7955
7943
  },
7956
7944
  {
7957
- id: 'runway-line-amm',
7958
- type: 'line',
7959
- source: sourceId,
7960
- 'source-layer': 'runway',
7961
- filter: ['has', 'has_amm'],
7962
- minzoom: 4,
7963
- maxzoom: 11,
7945
+ id: 'runway-line-amm', type: 'line', source: sourceId, 'source-layer': 'runway',
7946
+ filter: ['has', 'has_amm'], minzoom: 4, maxzoom: 11,
7964
7947
  paint: {
7965
- 'line-color': C.runway,
7948
+ 'line-color': T.runway,
7966
7949
  'line-width': ['interpolate', ['linear'], ['zoom'], 4, 1, 10, 4],
7967
7950
  'line-opacity': ['interpolate', ['linear'], ['zoom'], 10.5, 1, 11, 0],
7968
7951
  },
7969
7952
  },
7970
7953
  {
7971
- id: 'runway-label',
7972
- type: 'symbol',
7973
- source: sourceId,
7974
- 'source-layer': 'runway',
7975
- minzoom: 10,
7954
+ id: 'runway-label', type: 'symbol', source: sourceId, 'source-layer': 'runway', minzoom: 10,
7976
7955
  layout: {
7977
7956
  'text-field': ['concat', ['to-string', ['get', 'VAL_LEN']], '×', ['to-string', ['get', 'VAL_WID']], 'm'],
7978
7957
  'text-size': 10,
@@ -7981,28 +7960,16 @@ function buildLayersLight() {
7981
7960
  'text-optional': true,
7982
7961
  },
7983
7962
  paint: {
7984
- 'text-color': C.runway,
7985
- 'text-halo-width': 1,
7963
+ 'text-color': T.runway,
7964
+ ...T.runwayHalo,
7986
7965
  'text-opacity': ['interpolate', ['linear'], ['zoom'], 10.5, 1, 11, 0],
7987
7966
  },
7988
7967
  },
7989
7968
  {
7990
- id: 'vor_icon_dial',
7991
- type: 'symbol',
7992
- source: sourceId,
7993
- 'source-layer': 'vor',
7994
- minzoom: 8,
7969
+ id: 'vor_icon_dial', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 8,
7995
7970
  layout: {
7996
7971
  "icon-image": "vor:vor_dial",
7997
7972
  "icon-size": ["interpolate", ["linear"], ["zoom"], 8, 0.072, 10, 0.072, 11, 0.126, 12, 0.180, 13, 0.234, 14, 0.288, 15, 0.342, 16, 0.396, 17, 0.450, 22, 0.450],
7998
- // "icon-size": [
7999
- // "interpolate",
8000
- // ["exponential", 1.25],
8001
- // ["zoom"],
8002
- // 8, 0.28,
8003
- // 17, 1.7,
8004
- // 22, 1.7
8005
- // ],
8006
7973
  "icon-rotate": ["to-number", ["get", "VAL_MAG_VAR"], 0],
8007
7974
  "icon-rotation-alignment": "map",
8008
7975
  "symbol-z-order": "viewport-y",
@@ -8011,7 +7978,7 @@ function buildLayersLight() {
8011
7978
  "icon-allow-overlap": true,
8012
7979
  "visibility": "none",
8013
7980
  },
8014
- paint: { "icon-color": "#0b417a" }
7981
+ paint: { "icon-color": T.vorDial }
8015
7982
  },
8016
7983
  {
8017
7984
  id: 'vor_icon', minzoom: 4, maxzoom: 9, type: 'symbol', source: sourceId, 'source-layer': 'vor',
@@ -8025,45 +7992,25 @@ function buildLayersLight() {
8025
7992
  "icon-allow-overlap": true,
8026
7993
  },
8027
7994
  paint: {
8028
- "icon-color": "#3874cb",
7995
+ "icon-color": T.vorNormal,
8029
7996
  "icon-opacity": ["interpolate", ["linear"], ["zoom"], 8, 1, 9, 0],
8030
7997
  }
8031
7998
  },
8032
7999
  {
8033
8000
  id: 'vor_label', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 5,
8034
8001
  layout: { 'text-field': ['get', 'CODE_ID'], 'text-size': 10, 'text-anchor': 'bottom', 'text-offset': [0, -0.8] },
8035
- paint: { 'text-color': C.vor, 'text-halo-color': '#ffffff', 'text-halo-width': 1 },
8002
+ paint: { 'text-color': T.vor, 'text-halo-color': T.halo, 'text-halo-width': 1 },
8036
8003
  },
8037
8004
  {
8038
8005
  id: 'ndb_icon', type: 'symbol', source: sourceId, minzoom: 4, 'source-layer': 'ndb',
8039
8006
  layout: {
8040
- "icon-image": "v2:ndb-normal", "icon-size": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 10, 1],
8007
+ "icon-image": T.ndbIcon, "icon-size": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 10, 1],
8041
8008
  "symbol-z-order": "viewport-y",
8042
- // "text-field": ["concat", ["get", "CODE_ID"], "\n", ["get", "VAL_FREQ"], "kHz"],
8043
8009
  "text-field": [
8044
8010
  "format",
8045
- [
8046
- "get",
8047
- "CODE_ID"
8048
- ],
8049
- {
8050
- "text-color": C.ndb,
8051
- "font-scale": 1.1,
8052
- },
8053
- "",
8054
- {},
8055
- [
8056
- "coalesce",
8057
- [
8058
- "get",
8059
- "VAL_FREQ"
8060
- ],
8061
- ""
8062
- ],
8063
- {
8064
- "text-color": C.ndb,
8065
- "font-scale": 0.95
8066
- }
8011
+ ["get", "CODE_ID"], { "text-color": T.ndb, "font-scale": 1.1 },
8012
+ "", {},
8013
+ ["coalesce", ["get", "VAL_FREQ"], ""], { "text-color": T.ndb, "font-scale": 0.95 }
8067
8014
  ],
8068
8015
  "text-size": 10,
8069
8016
  "text-offset": [0, 0.5],
@@ -8073,53 +8020,11 @@ function buildLayersLight() {
8073
8020
  "text-anchor": "top"
8074
8021
  },
8075
8022
  paint: {
8076
- "text-color": C.ndb,
8077
- "text-halo-color": "#ffffff",
8078
- "text-halo-width": 0.5,
8079
- "text-halo-blur": 1,
8080
- "icon-color": C.ndb,
8081
- "text-opacity": [
8082
- "interpolate",
8083
- [
8084
- "linear"
8085
- ],
8086
- [
8087
- "zoom"
8088
- ],
8089
- 4,
8090
- 0,
8091
- 5.5,
8092
- 0,
8093
- 6,
8094
- 0.6,
8095
- 8,
8096
- 1,
8097
- 10,
8098
- 0.3,
8099
- 12,
8100
- 0
8101
- ],
8102
- "icon-opacity": [
8103
- "interpolate",
8104
- [
8105
- "linear"
8106
- ],
8107
- [
8108
- "zoom"
8109
- ],
8110
- 4,
8111
- 0,
8112
- 5,
8113
- 0.3,
8114
- 5.5,
8115
- 0.8,
8116
- 8,
8117
- 1,
8118
- 12,
8119
- 1,
8120
- 14,
8121
- 0.6
8122
- ]
8023
+ "text-color": T.ndb,
8024
+ ...T.ndbHalo,
8025
+ "icon-color": T.ndb,
8026
+ "text-opacity": ["interpolate", ["linear"], ["zoom"], 4, 0, 5.5, 0, 6, 0.6, 8, 1, 10, 0.3, 12, 0],
8027
+ "icon-opacity": ["interpolate", ["linear"], ["zoom"], 4, 0, 5, 0.3, 5.5, 0.8, 8, 1, 12, 1, 14, 0.6],
8123
8028
  }
8124
8029
  },
8125
8030
  {
@@ -8135,421 +8040,39 @@ function buildLayersLight() {
8135
8040
  'text-justify': 'auto',
8136
8041
  },
8137
8042
  paint: {
8138
- 'icon-color': C.waypoint,
8139
- 'text-color': C.waypoint,
8140
- 'text-halo-color': '#ffffff',
8141
- 'text-halo-width': 1,
8043
+ 'icon-color': T.waypoint,
8044
+ 'text-color': T.waypoint,
8142
8045
  "icon-halo-color": "rgba(0,0,0,0)",
8143
8046
  "icon-halo-width": 0,
8144
- "icon-opacity": [
8145
- "interpolate",
8146
- [
8147
- "linear"
8148
- ],
8149
- [
8150
- "zoom"
8151
- ],
8152
- 6,
8153
- 0.5,
8154
- 12,
8155
- 1,
8156
- 15,
8157
- 0.2
8158
- ],
8159
- "text-halo-color": "#FFFFFF",
8047
+ "icon-opacity": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 12, 1, 15, 0.2],
8048
+ "text-halo-color": T.halo,
8049
+ "text-halo-width": 1,
8160
8050
  "text-halo-blur": 0,
8161
- "text-opacity": [
8162
- "interpolate",
8163
- [
8164
- "linear"
8165
- ],
8166
- [
8167
- "zoom"
8168
- ],
8169
- 6,
8170
- 1,
8171
- 12,
8172
- 0.9,
8173
- 15,
8174
- 0.15
8175
- ],
8051
+ "text-opacity": ["interpolate", ["linear"], ["zoom"], 6, 1, 12, 0.9, 15, 0.15],
8176
8052
  },
8177
8053
  },
8178
8054
  {
8179
8055
  id: 'waypoint-off-airway-symbol', type: 'symbol', source: sourceId, 'source-layer': 'waypoint-off-airway', minzoom: 7,
8180
8056
  layout: { 'icon-image': ['case', ['==', ['get', 'report_type'], 'C'], 'designate_point_inway', 'designate_point_notinway'], 'icon-size': 0.6, 'icon-allow-overlap': true, 'icon-ignore-placement': true, 'text-field': ['get', 'CODE_ID'], 'text-size': 9, 'text-variable-anchor-offset': ['bottom', [0, -0.6], 'top', [0, 0.6], 'right', [-0.6, 0], 'left', [0.6, 0], 'bottom-right', [-0.4, -0.4], 'bottom-left', [0.4, -0.4], 'top-right', [-0.4, 0.4], 'top-left', [0.4, 0.4]], 'text-justify': 'auto', 'text-optional': true },
8181
8057
  paint: {
8182
- 'icon-color': C.waypoint, 'text-color': C.waypoint, 'text-halo-color': '#ffffff', 'text-halo-width': 1,
8183
- "icon-opacity": [
8184
- "interpolate",
8185
- [
8186
- "linear"
8187
- ],
8188
- [
8189
- "zoom"
8190
- ],
8191
- 7,
8192
- 0.5,
8193
- 12,
8194
- 1,
8195
- 15,
8196
- 0.2
8197
- ],
8198
- "text-opacity": [
8199
- "interpolate",
8200
- [
8201
- "linear"
8202
- ],
8203
- [
8204
- "zoom"
8205
- ],
8206
- 7,
8207
- 1,
8208
- 12,
8209
- 0.9,
8210
- 15,
8211
- 0.15
8212
- ],
8058
+ 'icon-color': T.waypoint, 'text-color': T.waypoint, 'text-halo-color': T.halo, 'text-halo-width': 1,
8059
+ "icon-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0.5, 12, 1, 15, 0.2],
8060
+ "text-opacity": ["interpolate", ["linear"], ["zoom"], 7, 1, 12, 0.9, 15, 0.15],
8213
8061
  },
8214
8062
  },
8215
8063
  ]
8216
8064
  }
8217
8065
 
8218
- // ── Dark theme ────────────────────────────────────────────────────────────────
8219
- const ICAO_DARK = {
8220
- airspaceStroke: '#18C29C',
8221
- restrictedStroke: '#CC7722',
8222
- controlledStroke: '#22C55E',
8223
- controlledFill: '#22C55E',
8224
- segment: '#40C4FF',
8225
- waypoint: '#74cdde',
8226
- vor: '#72aae5',
8227
- ndb: '#62d6ef',
8228
- airport: '#73ccdd',
8229
- runway: '#64748b',
8230
- };
8231
-
8232
- function buildLayersDark() {
8233
- const sourceId = 'navdata';
8234
- const C = ICAO_DARK;
8235
- return [
8236
- {
8237
- "id": "landLayer", "type": "fill", "source": "land",
8238
- "layout": { "visibility": "visible" },
8239
- "paint": { "fill-color": "#0A111A", "fill-opacity": 1 }
8240
- },
8241
- {
8242
- "id": "boundary",
8243
- "type": "line",
8244
- "source": "boundary",
8245
- "minzoom": 0,
8246
- "paint": {
8247
- "line-width": [
8248
- "interpolate",
8249
- [
8250
- "linear"
8251
- ],
8252
- [
8253
- "zoom"
8254
- ],
8255
- 0,
8256
- 1,
8257
- 7,
8258
- 4
8259
- ],
8260
- "line-opacity": 1,
8261
- "line-pattern": "normal:national-border-dark"
8262
- }
8263
- },
8264
- {
8265
- id: 'adiz-line', type: 'line', source: sourceId, 'source-layer': 'adiz', minzoom: 3,
8266
- layout: { 'line-cap': 'round', 'line-join': 'round' },
8267
- paint: { 'line-color': '#a855f7', 'line-width': ['interpolate', ['linear'], ['zoom'], 3, 3, 7, 6], "line-pattern": "normal:adiz", 'line-opacity': ['interpolate', ['linear'], ['zoom'], 3, 0.7, 8, 0.5] },
8268
- },
8269
- {
8270
- id: 'adiz-label', type: 'symbol', source: sourceId, 'source-layer': 'adiz-centroid', minzoom: 3,
8271
- layout: { 'text-field': ['coalesce', ['get', 'TXT_NAME'], ['get', 'CODE_ID']], 'text-size': 10, 'text-max-width': 10, 'symbol-placement': 'point' },
8272
- paint: { 'text-color': '#c084fc', 'text-halo-color': '#0f172a', 'text-halo-width': 1.5 },
8273
- },
8274
- {
8275
- id: 'airspaceLayer', type: 'line', source: sourceId, 'source-layer': 'fir', minzoom: 2,
8276
- layout: { "line-cap": "butt", "line-join": "miter", "line-miter-limit": 0 },
8277
- paint: { "line-color": C.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 2, 0, 2.7, 0.8, 9, 0.8, 10, 0.5], "line-width": 0.8, 'line-dasharray': [4.2, 4] }
8278
- },
8279
- {
8280
- "id": "airspaceLayer_line", type: 'line', source: sourceId, 'source-layer': 'fir', "minzoom": 5,
8281
- layout: { "line-miter-limit": 0, "line-cap": "butt", "line-join": "miter" },
8282
- paint: { "line-color": C.airspaceStroke, "line-opacity": ["interpolate", ["linear"], ["zoom"], 5, 0, 5.5, 0.8, 9, 0.8, 10, 0.5], "line-width": 5, "line-dasharray": [0.2, 5] }
8283
- },
8284
- {
8285
- id: 'airspace_label_side_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir', minzoom: 4,
8286
- layout: { 'text-field': ["concat", ["get", "TXT_NAME"], "/", ["get", "CODE_ID"], "/", ["get", "CODE_TYPE"]], 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1], "text-letter-spacing": 0.05, "text-optional": true },
8287
- paint: { 'text-color': C.airspaceStroke, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8288
- },
8289
- {
8290
- id: 'airspace_label_center_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir-centroid', minzoom: 3,
8291
- layout: {
8292
- 'text-field': ['coalesce', ['get', 'TXT_NAME'], ['get', 'CODE_ID']],
8293
- 'text-size': ['interpolate', ['linear'], ['zoom'], 3, 12, 17, 16],
8294
- 'symbol-placement': 'point',
8295
- 'text-max-width': 8,
8296
- },
8297
- paint: {
8298
- 'text-color': C.airspaceStroke,
8299
- 'text-halo-color': '#0f172a',
8300
- 'text-halo-width': 1.5,
8301
- 'text-opacity': ['interpolate', ['linear'], ['zoom'], 3, 0.85, 8, 0.7, 12, 0.5],
8302
- },
8303
- },
8304
- {
8305
- id: 'restrictedLayer', type: 'fill', source: sourceId, 'source-layer': 'restricted-fill', minzoom: 4,
8306
- paint: { 'fill-color': ['case', ['==', ['get', 'CODE_TYPE'], 'P'], '#ef4444', ['==', ['get', 'CODE_TYPE'], 'D'], '#f97316', '#ef4444'], 'fill-opacity': 0.04 },
8307
- },
8308
- {
8309
- id: 'restrictedLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'restricted',
8310
- paint: { 'line-color': C.restrictedStroke, 'line-width': 1, "line-dasharray": [2, 2], "line-opacity": ['interpolate', ['linear'], ['zoom'], 4, 0.6, 8, 1] },
8311
- },
8312
- {
8313
- id: 'restricted_line_label', type: 'symbol', source: sourceId, 'source-layer': 'restricted', minzoom: 6,
8314
- layout: { 'text-field': ['coalesce', ['get', 'TXT_NAME'], ['get', 'CODE_ID']], 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1] },
8315
- paint: { 'text-color': C.restrictedStroke, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8316
- },
8317
- {
8318
- id: 'controlledLayer', type: 'fill', source: sourceId, 'source-layer': 'controlled-fill', minzoom: 4,
8319
- paint: {
8320
- 'fill-color': C.controlledFill, "fill-opacity": [
8321
- "interpolate",
8322
- [
8323
- "linear"
8324
- ],
8325
- [
8326
- "zoom"
8327
- ],
8328
- 10,
8329
- 0.04,
8330
- 11.5,
8331
- 0
8332
- ]
8333
- },
8334
- },
8335
- {
8336
- id: 'controlledLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'controlled',
8337
- paint: { 'line-color': C.controlledStroke, 'line-width': 1, 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.6, 8, 1], "line-dasharray": [4, 2] },
8338
- },
8339
- {
8340
- id: 'controlled_line_label', type: 'symbol', source: sourceId, 'source-layer': 'controlled', minzoom: 6,
8341
- layout: { 'text-field': ['coalesce', ['get', 'TXT_NAME'], ['get', 'CODE_ID']], 'text-size': 10, 'symbol-placement': 'point', 'text-max-width': 8 },
8342
- paint: { 'text-color': C.controlledStroke, 'text-halo-color': '#0f172a', 'text-halo-width': 1.5 },
8343
- },
8344
- {
8345
- id: 'airline', type: 'line', source: sourceId, 'source-layer': 'segment', minzoom: 6,
8346
- paint: {
8347
- 'line-color': ['case', ['==', ['get', 'HAS_REMARK'], 1], '#fbbf24', C.segment],
8348
- 'line-width': ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
8349
- "line-blur": 0,
8350
- "line-opacity":
8351
- [
8352
- "interpolate",
8353
- [
8354
- "linear"
8355
- ],
8356
- [
8357
- "zoom"
8358
- ],
8359
- 6,
8360
- 0.3,
8361
- 7,
8362
- 1,
8363
- 8,
8364
- 1,
8365
- 12,
8366
- 0.8,
8367
- 15,
8368
- 0.2
8369
- ]
8370
- },
8371
- },
8372
- {
8373
- id: 'airline_label', type: 'symbol', source: sourceId, 'source-layer': 'segment', minzoom: 6,
8374
- layout: {
8375
- "icon-image": ["case", ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""], ["!=", ["get", "TXT_DESIG"], " "], ["!=", ["get", "TXT_DESIG"], null]], "segment-both", ["all", ["has", "TXT_DESIG_FORWARD"]], "segment-right", ["all", ["has", "TXT_DESIG_BACKWARD"]], "segment-left", "segment-both"],
8376
- "icon-anchor": "center", "symbol-placement": "line", "icon-text-fit": "width", "icon-size": 1,
8377
- "text-allow-overlap": false, "icon-allow-overlap": false,
8378
- "text-anchor": "center", "text-justify": "center", "text-line-height": 1.3, "text-letter-spacing": 0.1,
8379
- "text-field":
8380
- ["step", ["zoom"],
8381
- ["format", ["case", ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": "#0f172a" }],
8382
- 10,
8383
- ["format",
8384
- ["concat", ["get", "VAL_LEN"], "", ["get", "UOM_DIST"]], { "font-scale": 0.95, "text-color": "#cbd5e1" }, "\n",
8385
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""], ""], { "font-scale": 1, "text-color": "#FFFFFF" },
8386
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], " ", ""], ""], {},
8387
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG"], ["!=", ["get", "TXT_DESIG"], ""]], ["get", "TXT_DESIG"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": "#0f172a", "font-weight": "bold" },
8388
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], "", ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], " ", ""]], {},
8389
- ["case", ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], "", ["case", ["all", ["has", "TXT_DESIG_RNP"], ["!=", ["get", "TXT_DESIG_RNP"], ""]], ["get", "TXT_DESIG_RNP"], ""]], { "font-scale": 0.85, "text-color": "#FFFFFF" },
8390
- "\n",
8391
- ["case", ["all", ["has", "TXT_DESIG_HIGH"], ["!=", ["get", "TXT_DESIG_HIGH"], ""]], ["get", "TXT_DESIG_HIGH"], ["all", ["has", "TXT_DESIG_FORWARD"], ["!=", ["get", "TXT_DESIG_FORWARD"], ""]], ["get", "TXT_DESIG_FORWARD"], ["all", ["has", "TXT_DESIG_BACKWARD"], ["!=", ["get", "TXT_DESIG_BACKWARD"], ""]], ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 0.95, "text-color": "#cbd5e1" }
8392
- ]
8393
- ],
8394
- "text-size": ["interpolate", ["linear"], ["zoom"], 6, 9, 10, 10],
8395
- "icon-text-fit-padding": [0, 3, 0, 3],
8396
- },
8397
- paint: { "icon-color": C.segment },
8398
- },
8399
- {
8400
- id: 'airline_radial', type: 'symbol', source: sourceId, 'source-layer': 'segment-radial', minzoom: 13,
8401
- layout: { 'text-field': ['concat', ['get', 'bearing'], '°'], 'text-size': 9, 'text-rotate': ['to-number', ['get', 'line_angle'], 0], 'text-rotation-alignment': 'map', 'text-allow-overlap': true, 'text-ignore-placement': true, 'text-offset': [0, -1] },
8402
- paint: { 'text-color': C.segment, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8403
- },
8404
- {
8405
- id: 'airport', type: 'symbol', source: sourceId, minzoom: 3, 'source-layer': 'airport',
8406
- filter: ['case', ['<', ['zoom'], 6], ['==', ['get', 'level'], 1], true],
8407
- layout: {
8408
- "icon-image": ["case", ["==", ["get", "CODE_TYPE_MIL_OPS"], "MIL"], "airport-mil", ["==", ["get", "CODE_TYPE_MIL_OPS"], "MILEXT"], "airport-milext", "airport-civ"], "icon-size": ["interpolate", ["linear"], ["zoom"], 4, 0.5, 10, 0.9], "symbol-z-order": "viewport-y", "text-field": ["get", "codeId"],
8409
- "text-letter-spacing": 0.05,
8410
- "text-anchor": "bottom",
8411
- 'text-field': ['get', 'CODE_ID'],
8412
- "text-justify": "center",
8413
- "text-size": ["interpolate", ["linear"], ["zoom"], 4, 0, 5, 12],
8414
- "text-offset": ["interpolate", ["linear"], ["zoom"], 4, ["literal", [0, -1.2]], 5, ["literal", [0, -0.6]]],
8415
- "icon-allow-overlap": true,
8416
- "icon-ignore-placement": true,
8417
- "text-allow-overlap": true,
8418
- "text-ignore-placement": true,
8419
- "visibility": "none",
8420
- "icon-size": [
8421
- "interpolate",
8422
- [
8423
- "linear"
8424
- ],
8425
- [
8426
- "zoom"
8427
- ],
8428
- 5,
8429
- 0.6,
8430
- 9,
8431
- 1.2,
8432
- 12,
8433
- 1.3
8434
- ]
8435
- },
8436
- paint: {
8437
- 'icon-color': ['case',
8438
- ['has', 'has_amm'], '#4B2D6E',
8439
- C.airport,
8440
- ],
8441
- "icon-opacity": [
8442
- "interpolate",
8443
- [
8444
- "linear"
8445
- ],
8446
- [
8447
- "zoom"
8448
- ],
8449
- 2,
8450
- 0.75,
8451
- 3,
8452
- 0.95,
8453
- 5,
8454
- 1,
8455
- 9,
8456
- 1,
8457
- 11,
8458
- 0.2
8459
- ],
8460
- "text-color": ['case',
8461
- ['has', 'has_amm'], '#4B2D6E',
8462
- "#E0F7FA",
8463
- ],
8464
- "text-opacity": [
8465
- "interpolate",
8466
- [
8467
- "linear"
8468
- ],
8469
- [
8470
- "zoom"
8471
- ],
8472
- 4,
8473
- 0.95,
8474
- 5,
8475
- 1,
8476
- 9,
8477
- 1,
8478
- 11,
8479
- 0.2
8480
- ],
8481
- },
8482
- },
8483
- {
8484
- id: 'runway-line', type: 'line', source: sourceId, 'source-layer': 'runway', filter: ['!', ['has', 'has_amm']], minzoom: 4,
8485
- paint: { 'line-color': C.runway, 'line-width': ['interpolate', ['linear'], ['zoom'], 4, 1, 10, 3] },
8486
- },
8487
- {
8488
- id: 'runway-line-amm', type: 'line', source: sourceId, 'source-layer': 'runway', filter: ['has', 'has_amm'], minzoom: 4,
8489
- paint: { 'line-color': C.runway, 'line-width': ['interpolate', ['linear'], ['zoom'], 4, 1, 10, 3], 'line-opacity': ['interpolate', ['linear'], ['zoom'], 10.5, 1, 11, 0] },
8490
- },
8491
- {
8492
- id: 'runway-label', type: 'symbol', source: sourceId, 'source-layer': 'runway', minzoom: 10,
8493
- layout: { 'text-field': ['concat', ['to-string', ['get', 'VAL_LEN']], '×', ['to-string', ['get', 'VAL_WID']], 'm'], 'text-size': 10, 'text-font': ['Noto Sans Regular'], 'symbol-placement': 'line-center', 'text-rotation-alignment': 'map', 'text-optional': true },
8494
- paint: { 'text-color': C.runway, 'text-halo-color': '#0f172a', 'text-halo-width': 1, 'text-opacity': ['interpolate', ['linear'], ['zoom'], 10.5, 1, 11, 0] },
8495
- },
8496
- {
8497
- id: 'vor_icon_dial', type: 'symbol', source: sourceId, 'source-layer': 'vor',
8498
- layout: { "icon-image": "vor:vor_dial", "icon-size": ["interpolate", ["linear"], ["zoom"], 5, 0.072, 10, 0.072, 11, 0.126, 12, 0.180, 13, 0.234, 14, 0.288, 15, 0.342, 16, 0.396, 17, 0.450, 22, 0.450], "icon-rotate": ["to-number", ["get", "VAL_MAG_VAR"], 0], "icon-rotation-alignment": "map", "symbol-z-order": "viewport-y", "text-letter-spacing": 0.05, "text-optional": true, "icon-allow-overlap": true, "visibility": "none" },
8499
- paint: { "icon-color": "#38bdf8" }
8500
- },
8501
- {
8502
- id: 'vor_icon', minzoom: 4, maxzoom: 9, type: 'symbol', source: sourceId, 'source-layer': 'vor',
8503
- layout: {
8504
- "icon-image": "v2:vor-normal",
8505
- "icon-size": ["interpolate", ["linear"], ["zoom"], 4, 0.7, 8, 1],
8506
- "icon-rotation-alignment": "map",
8507
- "symbol-z-order": "viewport-y",
8508
- "text-letter-spacing": 0.05,
8509
- "text-optional": true,
8510
- "icon-allow-overlap": true,
8511
- },
8512
- paint: {
8513
- "icon-color": "#38bdf8",
8514
- "icon-opacity": ["interpolate", ["linear"], ["zoom"], 8, 1, 9, 0],
8515
- }
8516
- },
8517
- {
8518
- id: 'vor_label', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 5,
8519
- layout: { 'text-field': ['get', 'CODE_ID'], 'text-size': 10, 'text-anchor': 'bottom', 'text-offset': [0, -0.8] },
8520
- paint: { 'text-color': C.vor, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8521
- },
8522
- {
8523
- id: 'ndb_icon', type: 'symbol', source: sourceId, minzoom: 4, 'source-layer': 'ndb',
8524
- layout: { "icon-image": "ndb-inway", "icon-size": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 10, 1], "symbol-z-order": "viewport-y", "text-field": ["concat", ["get", "CODE_ID"], "\n", ["get", "VAL_FREQ"], "kHz"], "text-size": 10, "text-offset": [0, 1.4], "text-letter-spacing": 0.05, "text-optional": true, "icon-allow-overlap": true },
8525
- paint: { "text-color": C.ndb, "text-halo-color": "#0f172a", "text-halo-width": 1, "icon-color": C.ndb }
8526
- },
8527
- {
8528
- id: 'airline_point', type: 'symbol', source: sourceId, 'source-layer': 'waypoint', minzoom: 6,
8529
- layout: { 'icon-image': ['case', ['==', ['get', 'report_type'], 'C'], 'waypoint-compusory', 'waypoint'], 'icon-size': 0.6, 'icon-allow-overlap': true, 'icon-ignore-placement': true, 'text-field': ['get', 'CODE_ID'], 'text-size': 9, 'text-variable-anchor-offset': ['bottom', [0, -0.6], 'top', [0, 0.6], 'right', [-0.6, 0], 'left', [0.6, 0], 'bottom-right', [-0.4, -0.4], 'bottom-left', [0.4, -0.4], 'top-right', [-0.4, 0.4], 'top-left', [0.4, 0.4]], 'text-justify': 'auto', 'text-optional': true },
8530
- paint: { 'icon-color': C.waypoint, 'text-color': C.waypoint, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8531
- },
8532
- {
8533
- id: 'waypoint-off-airway-symbol', type: 'symbol', source: sourceId, 'source-layer': 'waypoint-off-airway', minzoom: 7,
8534
- layout: { 'icon-image': ['case', ['==', ['get', 'report_type'], 'C'], 'designate_point_inway', 'designate_point_notinway'], 'icon-size': 0.6, 'icon-allow-overlap': true, 'icon-ignore-placement': true, 'text-field': ['get', 'CODE_ID'], 'text-size': 9, 'text-variable-anchor-offset': ['bottom', [0, -0.6], 'top', [0, 0.6], 'right', [-0.6, 0], 'left', [0.6, 0], 'bottom-right', [-0.4, -0.4], 'bottom-left', [0.4, -0.4], 'top-right', [-0.4, 0.4], 'top-left', [0.4, 0.4]], 'text-justify': 'auto', 'text-optional': true },
8535
- paint: { 'icon-color': C.waypoint, 'text-color': C.waypoint, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
8536
- },
8537
- ]
8538
- }
8539
-
8540
-
8541
- // ── Theme registry
8542
- // Add new entries here to register additional chart styles.
8066
+ // ── Theme registry ──────────────────────────────────────────────────────────
8067
+ // 加主题 = 在 THEME_TOKENS 增加一张 token 表 + 在此登记。
8543
8068
  const CHART_THEMES = {
8544
- light: { id: 'light', label: '日间', background: '#EAF2F8', build: buildLayersLight },
8545
- dark: { id: 'dark', label: '夜间', background: '#000000', build: buildLayersDark },
8069
+ light: { id: 'light', label: '日间', background: '#EAF2F8' },
8070
+ dark: { id: 'dark', label: '夜间', background: '#000000' },
8071
+ dusk: { id: 'dusk', label: '暮光', background: '#1B2838' },
8072
+ foreflight: { id: 'foreflight', label: 'ForeFlight 风格', background: '#F2EFE6' },
8546
8073
  };
8547
8074
 
8548
- function buildLayers(themeId = 'light') {
8549
- return (CHART_THEMES[themeId] ?? CHART_THEMES.light).build()
8550
- }
8551
-
8552
- // ── Layer groups & labels (theme-independent)
8075
+ // ── Layer groups & labels (theme-independent) ────────────────────────────────
8553
8076
  const LAYER_GROUPS = {
8554
8077
  adiz: ['adiz-line', 'adiz-label'],
8555
8078
  airspace: ['airspaceLayer', 'airspaceLayer_line', 'airspace_label_center_layer', 'airspace_label_side_layer'],
@@ -8656,7 +8179,8 @@ class MapSDK {
8656
8179
  initializeMap(options) {
8657
8180
  this._baseUrl = options.staticUrl || "https://aips.siniswift.com";
8658
8181
  this._chartApiUrl = (options.apiUrl || DEFAULT_CHART_API_URL).replace(/\/$/, "");
8659
- const themeId = options.theme === "dark" ? "dark" : "light";
8182
+ this._apiVersion = options.apiVersion || undefined;
8183
+ const themeId = this._resolveThemeId(options.theme);
8660
8184
  const themeConfig = CHART_THEMES[themeId] ?? CHART_THEMES.light;
8661
8185
  const style = options.style ??
8662
8186
  getAviationBaseStyle({
@@ -8810,9 +8334,9 @@ class MapSDK {
8810
8334
  return;
8811
8335
  }
8812
8336
  if (!this.map.getSource("navdata")) {
8813
- this.map.addSource("navdata", getNavdataSource(this._chartApiUrl, period));
8337
+ this.map.addSource("navdata", getNavdataSource(this._chartApiUrl, period, this._apiVersion));
8814
8338
  }
8815
- const themeId = this.initialOptions.theme === "dark" ? "dark" : "light";
8339
+ const themeId = this._resolveThemeId(this.initialOptions.theme);
8816
8340
  for (const layer of buildLayers(themeId)) {
8817
8341
  if (this.map.getLayer(layer.id))
8818
8342
  continue;
@@ -8821,7 +8345,7 @@ class MapSDK {
8821
8345
  this.map.addLayer(layer);
8822
8346
  }
8823
8347
  if (!this.map.getSource("amm")) {
8824
- this.map.addSource("amm", getChartAmmSource(this._chartApiUrl));
8348
+ this.map.addSource("amm", getChartAmmSource(this._chartApiUrl, this._apiVersion));
8825
8349
  }
8826
8350
  const ammBefore = this.map.getLayer("airspaceLayer") ? "airspaceLayer" : undefined;
8827
8351
  for (const layer of buildAMMLayers("amm", themeId)) {
@@ -8953,8 +8477,8 @@ class MapSDK {
8953
8477
  });
8954
8478
  }
8955
8479
  setTheme(theme) {
8956
- const prevTheme = globalConfig.getConfig().styleConfig?.theme ||
8957
- "light";
8480
+ theme = this._resolveThemeId(theme);
8481
+ const prevTheme = this._resolveThemeId(globalConfig.getConfig().styleConfig?.theme);
8958
8482
  if (prevTheme === theme)
8959
8483
  return;
8960
8484
  globalConfig.updateConfigItem("styleConfig", {
@@ -8970,6 +8494,9 @@ class MapSDK {
8970
8494
  this._applyThemedProps(id, prevDefs[id], nextDefs[id]);
8971
8495
  }
8972
8496
  }
8497
+ _resolveThemeId(theme) {
8498
+ return theme && CHART_THEMES[theme] ? theme : "light";
8499
+ }
8973
8500
  _themeLayerDefs(theme) {
8974
8501
  const themeConfig = CHART_THEMES[theme] ?? CHART_THEMES.light;
8975
8502
  const defs = {
@@ -9150,7 +8677,7 @@ class MapSDK {
9150
8677
  this.globalConfig.setPeriod(period);
9151
8678
  const navdata = this.map?.getSource("navdata");
9152
8679
  if (navdata?.setTiles) {
9153
- navdata.setTiles([navdataTilesUrl(this._chartApiUrl, period)]);
8680
+ navdata.setTiles([navdataTilesUrl(this._chartApiUrl, period, this._apiVersion)]);
9154
8681
  }
9155
8682
  if (from !== undefined && from !== period) {
9156
8683
  this.map?.fire("periodchange", { from, to: period });
@@ -9168,7 +8695,7 @@ class MapSDK {
9168
8695
  return searchFeatures(this._chartApiUrl, apiKey, {
9169
8696
  ...params,
9170
8697
  ...(period ? { period } : {}),
9171
- });
8698
+ }, this._apiVersion);
9172
8699
  }
9173
8700
  getGeometry(params) {
9174
8701
  const apiKey = this.globalConfig.getConfig().apiKey;
@@ -9176,11 +8703,11 @@ class MapSDK {
9176
8703
  return getFeatureGeometry(this._chartApiUrl, apiKey, {
9177
8704
  ...params,
9178
8705
  ...(period ? { period } : {}),
9179
- });
8706
+ }, this._apiVersion);
9180
8707
  }
9181
8708
  getPeriods(signal) {
9182
8709
  const apiKey = this.globalConfig.getConfig().apiKey;
9183
- return getPeriods(this._chartApiUrl, apiKey, signal);
8710
+ return getPeriods(this._chartApiUrl, apiKey, signal, this._apiVersion);
9184
8711
  }
9185
8712
  showGraticule() {
9186
8713
  this.graticule?.show();
@@ -9264,6 +8791,8 @@ class MapSDK {
9264
8791
  if (options.baseUrl)
9265
8792
  config.baseUrl = options.baseUrl;
9266
8793
  config.apiUrl = this._chartApiUrl;
8794
+ if (this._apiVersion)
8795
+ config.apiVersion = this._apiVersion;
9267
8796
  if (options.period)
9268
8797
  config.period = options.period;
9269
8798
  globalConfig.setConfig(config);