aviation-chart 2.0.29 → 2.0.30

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.
@@ -1332,15 +1332,15 @@ const AMM_COLOR_LIGHT = {
1332
1332
  /** 机场边界(淡暖灰垫底,在纯白底上显现轮廓) */
1333
1333
  airport: '#e2e8f0',
1334
1334
  /** 跑道面(中深灰,作为白底上的绝对重心) */
1335
- runway: '#94a3b8',
1335
+ runway: 'hsl(0, 0%, 33%)',
1336
1336
  /** 机坪面(中浅灰,与白底拉开清晰明度差) */
1337
- apron: '#cbd5e1',
1337
+ apron: 'hsl(0, 0%, 60%)',
1338
1338
  /** 滑行道面(带微弱色调差的浅灰,与机坪剥离) */
1339
- taxiway: '#e2e8f0',
1339
+ taxiway: 'hsl(240, 5%, 60%)',
1340
1340
  /** 滑行道中心线(深琥珀金,白底上极清晰) */
1341
- taxiwayLine: '#f59e0b',
1341
+ taxiwayLine: '#ffff00',
1342
1342
  /** 等待位(深砖红/铁锈红,高辨识度) */
1343
- holding: '#b91c1c',
1343
+ holding: 'hsl(0, 100%, 50%)',
1344
1344
  /** 机位点(深翡翠绿) */
1345
1345
  stand: '#1e293b',
1346
1346
  /** 跑道标记(涂装面) */
@@ -1348,7 +1348,7 @@ const AMM_COLOR_LIGHT = {
1348
1348
  /** 跑道中心线 */
1349
1349
  runwayCenterline: '#ffffff',
1350
1350
  /** 停机位引导线(深绿色) */
1351
- standLine: '#64748b',
1351
+ standLine: '#010101',
1352
1352
  /** 跑道入口点(深琥珀色) */
1353
1353
  threshold: '#c2410c',
1354
1354
  /** 限制区域(深红) */
@@ -1357,9 +1357,9 @@ const AMM_COLOR_LIGHT = {
1357
1357
  hotspot: '#ea580c',
1358
1358
  };
1359
1359
 
1360
- function buildAMMLayersLight(sourceId = 'amm') {
1361
- const C = AMM_COLOR_LIGHT;
1362
- return [
1360
+ function buildAMMLayersLight(sourceId = 'amm', colors = AMM_COLOR_LIGHT) {
1361
+ const C = colors;
1362
+ const layers = [
1363
1363
  // ── 机场边界轮廓(z11+)
1364
1364
  {
1365
1365
  id: 'amm-airport-fill',
@@ -1392,8 +1392,9 @@ function buildAMMLayersLight(sourceId = 'amm') {
1392
1392
  'source-layer': 'amm-runway',
1393
1393
  minzoom: 11,
1394
1394
  paint: {
1395
+ "fill-antialias": true,
1395
1396
  'fill-color': C.runway,
1396
- 'fill-opacity': 0.9,
1397
+ 'fill-opacity': 1,
1397
1398
  },
1398
1399
  },
1399
1400
  {
@@ -1417,20 +1418,39 @@ function buildAMMLayersLight(sourceId = 'amm') {
1417
1418
  'source-layer': 'amm-apron',
1418
1419
  minzoom: 11,
1419
1420
  paint: {
1421
+ "fill-antialias": true,
1420
1422
  'fill-color': C.apron,
1421
- 'fill-opacity': 0.6, // 提高透明度浓度
1423
+ 'fill-opacity': 1, // 提高透明度浓度
1422
1424
  },
1423
1425
  },
1424
1426
  {
1425
- id: 'amm-apron-stroke',
1426
- type: 'line',
1427
+ id: 'amm-apron-label',
1428
+ type: 'symbol',
1427
1429
  source: sourceId,
1428
1430
  'source-layer': 'amm-apron',
1429
- minzoom: 11,
1430
- paint: {
1431
- 'line-color': '#94a3b8', // 勾边加深,确保纯白背景下清晰可见
1432
- 'line-width': 0.5,
1431
+ minzoom: 13,
1432
+ "layout": {
1433
+ "text-ignore-placement": false,
1434
+ "text-allow-overlap": false,
1435
+ "text-size": 10,
1436
+ "text-font": ["Fira Code SemiBold"],
1437
+ "text-field": [
1438
+ "case",
1439
+ [
1440
+ "any",
1441
+ ["!", ["has", "idapron"]],
1442
+ ["==", ["get", "idapron"], null],
1443
+ ["==", ["get", "idapron"], "null"]
1444
+ ],
1445
+ "",
1446
+ ["to-string", ["get", "idapron"]]
1447
+ ]
1433
1448
  },
1449
+ "paint": {
1450
+ "text-color": "#fefefe",
1451
+ "text-halo-color": "#010101",
1452
+ "text-halo-width": 0.5
1453
+ }
1434
1454
  },
1435
1455
 
1436
1456
  // ── 滑行道面(z11+)───
@@ -1441,8 +1461,21 @@ function buildAMMLayersLight(sourceId = 'amm') {
1441
1461
  'source-layer': 'amm-taxiway',
1442
1462
  minzoom: 11,
1443
1463
  paint: {
1464
+ "fill-antialias": true,
1444
1465
  'fill-color': C.taxiway,
1445
- 'fill-opacity': 0.7,
1466
+ "fill-opacity": {
1467
+ "base": 1,
1468
+ "stops": [
1469
+ [
1470
+ 11,
1471
+ 0
1472
+ ],
1473
+ [
1474
+ 12,
1475
+ 1
1476
+ ]
1477
+ ]
1478
+ }
1446
1479
  },
1447
1480
  },
1448
1481
 
@@ -1452,12 +1485,40 @@ function buildAMMLayersLight(sourceId = 'amm') {
1452
1485
  type: 'line',
1453
1486
  source: sourceId,
1454
1487
  'source-layer': 'amm-taxiway-line',
1455
- minzoom: 11,
1488
+ minzoom: 13.5,
1489
+ paint: {
1490
+ 'line-color': C.taxiwayLine,
1491
+ 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 0.8, 18, 2]
1492
+ },
1493
+ },
1494
+ // 滑行道引导线
1495
+ {
1496
+ id: 'amm-taxiway-guidanceline',
1497
+ type: 'line',
1498
+ source: sourceId,
1499
+ 'source-layer': 'amm-taxiway-guidance-line',
1500
+ minzoom: 13.5,
1456
1501
  paint: {
1457
1502
  'line-color': C.taxiwayLine,
1458
1503
  'line-width': ['interpolate', ['linear'], ['zoom'], 15, 0.8, 18, 2]
1459
1504
  },
1460
1505
  },
1506
+ // 滑行道交叉线
1507
+ {
1508
+ id: 'amm-taxiway-intersectionline',
1509
+ type: 'line',
1510
+ source: sourceId,
1511
+ 'source-layer': 'amm-taxiway-intersection-marking',
1512
+ minzoom: 13.5,
1513
+ paint: {
1514
+ 'line-color': "#fff",
1515
+ 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 0.8, 18, 2],
1516
+ "line-dasharray": [
1517
+ 3,
1518
+ 3
1519
+ ]
1520
+ },
1521
+ },
1461
1522
 
1462
1523
 
1463
1524
  // ── 等待位(z11+)─────
@@ -1466,12 +1527,58 @@ function buildAMMLayersLight(sourceId = 'amm') {
1466
1527
  type: 'line',
1467
1528
  source: sourceId,
1468
1529
  'source-layer': 'amm-holding',
1469
- minzoom: 11,
1530
+ minzoom: 13,
1470
1531
  paint: {
1471
1532
  'line-color': C.holding,
1472
1533
  'line-width': 1.5,
1473
1534
  },
1474
1535
  },
1536
+ {
1537
+ id: 'amm-holding-label',
1538
+ type: 'symbol',
1539
+ source: sourceId,
1540
+ 'source-layer': 'amm-holding',
1541
+ minzoom: 15,
1542
+ "layout": {
1543
+ "text-offset": [
1544
+ 0,
1545
+ 0
1546
+ ],
1547
+ "symbol-placement": "point",
1548
+ "text-ignore-placement": true,
1549
+ "text-allow-overlap": true,
1550
+ "text-size": 13,
1551
+ "text-font": [
1552
+ "Font17"
1553
+ ],
1554
+ "text-field": [
1555
+ "case",
1556
+ [
1557
+ "!=",
1558
+ [
1559
+ "get",
1560
+ "idlin"
1561
+ ],
1562
+ ""
1563
+ ],
1564
+ [
1565
+ "concat",
1566
+ ".",
1567
+ [
1568
+ "get",
1569
+ "idlin"
1570
+ ],
1571
+ "."
1572
+ ],
1573
+ ""
1574
+ ]
1575
+ },
1576
+ "paint": {
1577
+ "text-halo-color": C.holding,
1578
+ "text-color": "#010101",
1579
+ "text-halo-width": 2
1580
+ }
1581
+ },
1475
1582
 
1476
1583
  // ── 跑道标记(斑马线、编号等涂装面,z13+)─────────────────────────
1477
1584
  {
@@ -1481,6 +1588,7 @@ function buildAMMLayersLight(sourceId = 'amm') {
1481
1588
  'source-layer': 'amm-runway-marking',
1482
1589
  minzoom: 13,
1483
1590
  paint: {
1591
+ "fill-antialias": true,
1484
1592
  'fill-color': C.runwayMarking,
1485
1593
  'fill-opacity': 0.9,
1486
1594
  },
@@ -1494,20 +1602,9 @@ function buildAMMLayersLight(sourceId = 'amm') {
1494
1602
  'source-layer': 'amm-restricted',
1495
1603
  minzoom: 11,
1496
1604
  paint: {
1605
+ "fill-antialias": true,
1497
1606
  'fill-color': C.restricted,
1498
- 'fill-opacity': 0.08, // 针对白底降低面纯度
1499
- },
1500
- },
1501
- {
1502
- id: 'amm-restricted-stroke',
1503
- type: 'line',
1504
- source: sourceId,
1505
- 'source-layer': 'amm-restricted',
1506
- minzoom: 11,
1507
- paint: {
1508
- 'line-color': C.restricted,
1509
- 'line-width': 1.5,
1510
- 'line-dasharray': [4, 2],
1607
+ 'fill-opacity': 0.3, // 针对白底降低面纯度
1511
1608
  },
1512
1609
  },
1513
1610
 
@@ -1517,22 +1614,55 @@ function buildAMMLayersLight(sourceId = 'amm') {
1517
1614
  type: 'fill',
1518
1615
  source: sourceId,
1519
1616
  'source-layer': 'amm-hotspot',
1520
- minzoom: 11,
1521
- paint: {
1522
- 'fill-color': C.hotspot,
1523
- 'fill-opacity': 0.1, // 针对白底轻微淡化面
1524
- },
1617
+ minzoom: 12,
1618
+ "paint": {
1619
+ "fill-antialias": true,
1620
+ "fill-outline-color": "#ff00ff",
1621
+ "fill-color": "#89259D",
1622
+ "fill-opacity": 0.3
1623
+ }
1525
1624
  },
1526
1625
  {
1527
- id: 'amm-hotspot-stroke',
1528
- type: 'line',
1529
- source: sourceId,
1530
- 'source-layer': 'amm-hotspot',
1531
- minzoom: 11,
1532
- paint: {
1533
- 'line-color': C.hotspot,
1534
- 'line-width': 1.5,
1626
+ id: "amm-hotpost-label",
1627
+ "type": "symbol",
1628
+ "source": sourceId,
1629
+ "source-layer": "amm-hotspot",
1630
+ "minzoom": 12,
1631
+ "layout": {
1632
+ "symbol-placement": "point",
1633
+ "text-ignore-placement": false,
1634
+ "text-allow-overlap": false,
1635
+ "text-size": 14,
1636
+ "text-font": [
1637
+ "Font17"
1638
+ ],
1639
+ "text-field": [
1640
+ "case",
1641
+ [
1642
+ "!=",
1643
+ [
1644
+ "get",
1645
+ "idhot"
1646
+ ],
1647
+ ""
1648
+ ],
1649
+ [
1650
+ "concat",
1651
+ ".",
1652
+ [
1653
+ "get",
1654
+ "idhot"
1655
+ ],
1656
+ "."
1657
+ ],
1658
+ ""
1659
+ ]
1535
1660
  },
1661
+ "paint": {
1662
+ "text-color": "#444",
1663
+ "text-halo-color": "#ff00ff",
1664
+ "text-halo-width": 2
1665
+ }
1536
1666
  },
1537
1667
 
1538
1668
  // ── 跑道中心线(z11+)─────────────────────────────────────────────
@@ -1592,8 +1722,14 @@ function buildAMMLayersLight(sourceId = 'amm') {
1592
1722
  'source-layer': 'amm-stand-line',
1593
1723
  minzoom: 13,
1594
1724
  paint: {
1595
- 'line-color': C.standLine,
1596
- 'line-width': 1,
1725
+ 'line-color': '#ffff00',
1726
+ "line-width": [
1727
+ "interpolate",
1728
+ ["exponential", 1.8],
1729
+ ["zoom"],
1730
+ 13, 0.2,
1731
+ 15, 0.4
1732
+ ]
1597
1733
  },
1598
1734
  },
1599
1735
  // 滑行道名称(中心线 symbol)
@@ -1602,25 +1738,43 @@ function buildAMMLayersLight(sourceId = 'amm') {
1602
1738
  type: 'symbol',
1603
1739
  source: sourceId,
1604
1740
  'source-layer': 'amm-taxiway-line',
1605
- minzoom: 14,
1741
+ minzoom: 12,
1606
1742
  layout: {
1607
- 'text-field': ['get', 'idlin'],
1608
- 'text-size': 10,
1609
- "icon-image": "stretch:text_bg",
1610
- "icon-text-fit": "both",
1611
- "icon-text-fit-padding": [
1612
- 1,
1613
- 2,
1614
- 1,
1615
- 2
1743
+ "symbol-placement": "line",
1744
+ "text-ignore-placement": false,
1745
+ "text-allow-overlap": false,
1746
+ "text-size": 15,
1747
+ "text-max-angle": 10,
1748
+ "text-font": [
1749
+ "Font17"
1616
1750
  ],
1617
- 'symbol-placement': 'line',
1618
- 'text-keep-upright': true,
1619
- 'text-allow-overlap': false,
1751
+ "text-field": [
1752
+ "case",
1753
+ [
1754
+ "!=",
1755
+ [
1756
+ "get",
1757
+ "idlin"
1758
+ ],
1759
+ ""
1760
+ ],
1761
+ [
1762
+ "concat",
1763
+ ".",
1764
+ [
1765
+ "get",
1766
+ "idlin"
1767
+ ],
1768
+ "."
1769
+ ],
1770
+ ""
1771
+ ],
1772
+ "text-rotation-alignment": "viewport"
1620
1773
  },
1621
1774
  paint: {
1622
- 'text-color': "#FFF",
1623
- "icon-color": C.taxiwayLine
1775
+ "text-halo-color": "yellow",
1776
+ "text-color": "#010101",
1777
+ "text-halo-width": 2
1624
1778
  },
1625
1779
  },
1626
1780
 
@@ -1631,98 +1785,96 @@ function buildAMMLayersLight(sourceId = 'amm') {
1631
1785
  source: sourceId,
1632
1786
  'source-layer': 'amm-runway-threshold',
1633
1787
  minzoom: 12,
1634
- layout: {
1635
- "icon-image": "stretch:text_bg",
1636
- "icon-text-fit": "both",
1637
- "icon-text-fit-padding": [
1638
- 1,
1639
- 2,
1640
- 1,
1641
- 2
1788
+ "layout": {
1789
+ "symbol-placement": "point",
1790
+ "text-ignore-placement": false,
1791
+ "text-allow-overlap": false,
1792
+ "text-size": 14,
1793
+ "text-font": [
1794
+ "Font17"
1642
1795
  ],
1643
- 'text-field': ['get', 'idthr'],
1644
- 'text-size': 14,
1645
- 'text-allow-overlap': true,
1796
+ "text-field": "{idthr}",
1646
1797
  'text-rotation-alignment': 'map',
1647
- 'icon-rotation-alignment': 'map',
1648
- },
1649
- paint: {
1650
- 'text-color': '#fff',
1651
- "icon-color": "#b91c1c"
1652
1798
  },
1799
+ "paint": {
1800
+ "text-halo-color": "white",
1801
+ "text-color": "red",
1802
+ "text-halo-width": 2
1803
+ }
1653
1804
  },
1654
1805
 
1655
- // ── 机位点(z11+)─────
1656
- {
1657
- id: 'amm-stand',
1658
- type: 'circle',
1659
- source: sourceId,
1660
- 'source-layer': 'amm-stand',
1661
- minzoom: 12,
1662
- paint: {
1663
- 'circle-color': C.stand,
1664
- 'circle-radius': 1.5,
1665
- },
1666
- },
1667
1806
  // 机位编号标签
1668
1807
  {
1669
1808
  id: 'amm-stand-label',
1670
1809
  type: 'symbol',
1671
1810
  source: sourceId,
1672
1811
  'source-layer': 'amm-stand',
1673
- minzoom: 14,
1674
- layout: {
1675
- 'text-field': ['get', 'idstd'],
1676
- 'text-size': 9,
1677
- 'text-anchor': 'bottom',
1678
- 'text-offset': [0, -0.5],
1679
- 'text-allow-overlap': false,
1680
- },
1681
- paint: {
1682
- 'text-color': C.standLine, // 改为深墨绿字,白底/浅灰底上高可读
1812
+ minzoom: 13.5,
1813
+ "layout": {
1814
+ "symbol-placement": "point",
1815
+ "text-ignore-placement": false,
1816
+ "text-allow-overlap": false,
1817
+ "text-size": 14,
1818
+ "text-font": [
1819
+ "Font17"
1820
+ ],
1821
+ "text-field": [
1822
+ "case",
1823
+ [
1824
+ "!=",
1825
+ [
1826
+ "get",
1827
+ "idstd"
1828
+ ],
1829
+ ""
1830
+ ],
1831
+ [
1832
+ "concat",
1833
+ ".",
1834
+ [
1835
+ "get",
1836
+ "idstd"
1837
+ ],
1838
+ "."
1839
+ ],
1840
+ ""
1841
+ ],
1683
1842
  },
1843
+ "paint": {
1844
+ "text-halo-color": "#fefefe",
1845
+ "text-color": C.standLine,
1846
+ "text-halo-width": 2
1847
+ }
1684
1848
  },
1685
1849
 
1686
1850
 
1687
1851
  // ── 垂直面状障碍物(z11+)──────────────────────────────────────
1688
1852
  {
1689
1853
  id: 'amm-obstacle-region-fill',
1690
- type: 'fill',
1691
- source: sourceId,
1692
- 'source-layer': 'amm-obstacle-region',
1693
- minzoom: 11,
1694
- paint: {
1695
- 'fill-color': '#fef08a',
1696
- 'fill-opacity': 0.35,
1697
- },
1698
- },
1699
- {
1700
- id: 'amm-obstacle-region-stroke',
1701
- type: 'line',
1854
+ type: 'fill-extrusion',
1702
1855
  source: sourceId,
1703
1856
  'source-layer': 'amm-obstacle-region',
1704
1857
  minzoom: 11,
1705
1858
  paint: {
1706
- 'line-color': '#ca8a04',
1707
- 'line-width': 1.5,
1708
- 'line-dasharray': [1.5, 1]
1709
- },
1859
+ "fill-extrusion-height": 10,
1860
+ "fill-extrusion-color": 'hsl(240, 25%, 30%)',
1861
+ "fill-extrusion-opacity": {
1862
+ "base": 1,
1863
+ "stops": [
1864
+ [
1865
+ 11,
1866
+ 0
1867
+ ],
1868
+ [
1869
+ 12,
1870
+ 1
1871
+ ]
1872
+ ]
1873
+ }
1874
+ }
1710
1875
  },
1711
1876
 
1712
- // ── 垂直点状障碍物(z11+)──────────────────────────────────────
1713
- {
1714
- id: 'amm-obstacle-point',
1715
- type: 'circle',
1716
- source: sourceId,
1717
- 'source-layer': 'amm-obstacle-point',
1718
- minzoom: 11,
1719
- paint: {
1720
- 'circle-color': '#b45309',
1721
- 'circle-radius': 4,
1722
- 'circle-stroke-color': '#ffffff',
1723
- 'circle-stroke-width': 1,
1724
- },
1725
- },
1877
+
1726
1878
  // 点状障碍物名称标签
1727
1879
  {
1728
1880
  id: 'amm-obstacle-point-label',
@@ -1734,13 +1886,31 @@ function buildAMMLayersLight(sourceId = 'amm') {
1734
1886
  'text-field': ['coalesce', ['get', 'ident'], ['get', 'LABEL']],
1735
1887
  'text-size': 9,
1736
1888
  'text-anchor': 'bottom',
1737
- 'text-offset': [0, -0.5],
1738
- 'text-allow-overlap': false,
1889
+ 'text-offset': [0, -1],
1890
+ "icon-allow-overlap": true,
1891
+ "icon-image": 'navig:radio_tower',
1892
+ "icon-size": {
1893
+ "base": 2,
1894
+ "stops": [
1895
+ [
1896
+ 13,
1897
+ 0.5
1898
+ ],
1899
+ [
1900
+ 16,
1901
+ 1
1902
+ ]
1903
+ ]
1904
+ }
1739
1905
  },
1740
1906
  paint: {
1741
1907
  'text-color': '#92400e',
1742
1908
  'text-halo-color': '#ffffff',
1743
1909
  'text-halo-width': 1,
1910
+ "icon-color": "#010101",
1911
+ "icon-halo-color": "#fefefe",
1912
+ "icon-halo-width": 0.5,
1913
+ "icon-halo-blur": 0.5
1744
1914
  },
1745
1915
  },
1746
1916
 
@@ -1787,6 +1957,15 @@ function buildAMMLayersLight(sourceId = 'amm') {
1787
1957
  'text-halo-width': 1,
1788
1958
  },
1789
1959
  },
1960
+ ];
1961
+
1962
+ // 文字标注置于所有面、线和图标之后,避免被后续图层遮挡。
1963
+ const textLayers = layers.filter((layer) =>
1964
+ layer.type === 'symbol' && layer.layout?.['text-field'] !== undefined
1965
+ );
1966
+ return [
1967
+ ...layers.filter((layer) => !textLayers.includes(layer)),
1968
+ ...textLayers,
1790
1969
  ]
1791
1970
  }
1792
1971
 
@@ -1808,62 +1987,7 @@ const AMM_COLOR_DARK = {
1808
1987
  };
1809
1988
 
1810
1989
  function buildAMMLayersDark(sourceId = 'amm') {
1811
- const C = AMM_COLOR_DARK;
1812
- return [
1813
- { id: 'amm-airport-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-airport', minzoom: 11, paint: { 'fill-color': C.airport, 'fill-opacity': 0.3 } },
1814
- { id: 'amm-airport-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-airport', minzoom: 11, paint: { 'line-color': '#475569', 'line-width': 1 } },
1815
- { id: 'amm-runway-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-runway', minzoom: 11, paint: { 'fill-color': C.runway, 'fill-opacity': 1 } },
1816
- { id: 'amm-runway-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-runway', minzoom: 11, paint: { 'line-color': '#64748b', 'line-width': 0.5 } },
1817
- { id: 'amm-apron-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-apron', minzoom: 11, paint: { 'fill-color': C.apron, 'fill-opacity': 1 } },
1818
- { id: 'amm-apron-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-apron', minzoom: 11, paint: { 'line-color': '#334155', 'line-width': 0.5 } },
1819
- { id: 'amm-taxiway-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-taxiway', minzoom: 11, paint: { 'fill-color': C.taxiway, 'fill-opacity': 0.8 } },
1820
- { id: 'amm-taxiway-line', type: 'line', source: sourceId, 'source-layer': 'amm-taxiway-line', minzoom: 11, paint: { 'line-color': C.taxiwayLine, 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 0.8, 18, 2] } },
1821
-
1822
- { id: 'amm-holding', type: 'line', source: sourceId, 'source-layer': 'amm-holding', minzoom: 11, paint: { 'line-color': C.holding, 'line-width': 1.5 } },
1823
- { id: 'amm-runway-marking', type: 'fill', source: sourceId, 'source-layer': 'amm-runway-marking', minzoom: 13, paint: { 'fill-color': C.runwayMarking, 'fill-opacity': 0.8 } },
1824
- { id: 'amm-restricted-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-restricted', minzoom: 11, paint: { 'fill-color': C.restricted, 'fill-opacity': 0.12 } },
1825
- { id: 'amm-restricted-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-restricted', minzoom: 11, paint: { 'line-color': C.restricted, 'line-width': 1.2, 'line-dasharray': [4, 2] } },
1826
- { id: 'amm-hotspot-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-hotspot', minzoom: 11, paint: { 'fill-color': C.hotspot, 'fill-opacity': 0.15 } },
1827
- { id: 'amm-hotspot-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-hotspot', minzoom: 11, paint: { 'line-color': C.hotspot, 'line-width': 1.2 } },
1828
- { id: 'amm-runway-centerline', type: 'line', source: sourceId, 'source-layer': 'amm-runway-centerline', minzoom: 11, paint: { 'line-color': C.runwayCenterline, 'line-width': 1, 'line-dasharray': [6, 3] } },
1829
- {
1830
- id: 'amm-runway-info', type: 'symbol', source: sourceId, 'source-layer': 'amm-runway-label', minzoom: 13,
1831
- layout: { 'text-field': ['concat', ['coalesce', ['get', 'length'], ''], '×', ['coalesce', ['get', 'width'], ''], 'm'], 'text-size': ['interpolate', ['exponential', 1.5], ['zoom'], 13, 10, 16, 13], 'symbol-placement': 'point', 'text-rotate': ['coalesce', ['get', 'bearing'], 0], 'text-rotation-alignment': 'map', 'text-allow-overlap': true, 'text-ignore-placement': true },
1832
- paint: { 'text-color': '#e2e8f0', 'text-halo-color': '#0f172a', 'text-halo-width': 2 },
1833
- },
1834
- { id: 'amm-stand-line', type: 'line', source: sourceId, 'source-layer': 'amm-stand-line', minzoom: 13, paint: { 'line-color': C.standLine, 'line-width': 1 } },
1835
- {
1836
- id: 'amm-taxiway-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-taxiway-line', minzoom: 14,
1837
- layout: { 'text-field': ['get', 'idlin'], 'text-size': 10, "icon-image": "stretch:text_bg", "icon-text-fit": "both", "icon-text-fit-padding": [1, 2, 1, 2], 'symbol-placement': 'line', 'text-keep-upright': true, 'text-allow-overlap': false },
1838
- paint: { 'text-color': "#0f172a", "icon-color": C.taxiwayLine },
1839
- },
1840
- {
1841
- id: 'amm-runway-threshold-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-runway-threshold', minzoom: 12,
1842
- layout: { "icon-image": "stretch:text_bg", "icon-text-fit": "both", "icon-text-fit-padding": [1, 2, 1, 2], 'text-field': ['get', 'idthr'], 'text-size': 14, 'text-allow-overlap': true, 'text-rotation-alignment': 'map', 'icon-rotation-alignment': 'map' },
1843
- paint: { 'text-color': '#ffffff', "icon-color": "#ef4444" },
1844
- },
1845
- { id: 'amm-stand', type: 'circle', source: sourceId, 'source-layer': 'amm-stand', minzoom: 12, paint: { 'circle-color': C.stand, 'circle-radius': 1.5 } },
1846
- {
1847
- id: 'amm-stand-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-stand', minzoom: 14,
1848
- layout: { 'text-field': ['get', 'idstd'], 'text-size': 9, 'text-anchor': 'bottom', 'text-offset': [0, -0.5], 'text-allow-overlap': false },
1849
- paint: { 'text-color': C.stand, 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
1850
- },
1851
- { id: 'amm-obstacle-region-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-obstacle-region', minzoom: 11, paint: { 'fill-color': '#fef08a', 'fill-opacity': 0.15 } },
1852
- { id: 'amm-obstacle-region-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-obstacle-region', minzoom: 11, paint: { 'line-color': '#eab308', 'line-width': 1.2, 'line-dasharray': [1.5, 1] } },
1853
- { id: 'amm-obstacle-point', type: 'circle', source: sourceId, 'source-layer': 'amm-obstacle-point', minzoom: 11, paint: { 'circle-color': '#f97316', 'circle-radius': 4, 'circle-stroke-color': '#0f172a', 'circle-stroke-width': 1 } },
1854
- {
1855
- id: 'amm-obstacle-point-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-obstacle-point', minzoom: 14,
1856
- layout: { 'text-field': ['coalesce', ['get', 'ident'], ['get', 'LABEL']], 'text-size': 9, 'text-anchor': 'bottom', 'text-offset': [0, -0.5], 'text-allow-overlap': false },
1857
- paint: { 'text-color': '#fdba74', 'text-halo-color': '#0f172a', 'text-halo-width': 1.2 },
1858
- },
1859
- { id: 'amm-construction-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-construction', minzoom: 11, paint: { 'fill-pattern': 'normal:passline', 'fill-opacity': 0.6 } },
1860
- { id: 'amm-construction-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-construction', minzoom: 11, paint: { 'line-color': '#ea580c', 'line-width': 1.2, 'line-dasharray': [4, 2] } },
1861
- {
1862
- id: 'amm-construction-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-construction', minzoom: 13,
1863
- layout: { 'text-field': ['get', 'text'], 'text-size': 9, 'text-anchor': 'center', 'symbol-placement': 'point', 'text-allow-overlap': false },
1864
- paint: { 'text-color': '#f97316', 'text-halo-color': '#0f172a', 'text-halo-width': 1 },
1865
- },
1866
- ]
1990
+ return buildAMMLayersLight(sourceId, AMM_COLOR_DARK)
1867
1991
  }
1868
1992
 
1869
1993
  // ── Neutral (Charcoal) theme ──────────────────────────────────────────────────
@@ -1884,62 +2008,7 @@ const AMM_COLOR_NEUTRAL = {
1884
2008
  };
1885
2009
 
1886
2010
  function buildAMMLayersNeutral(sourceId = 'amm') {
1887
- const C = AMM_COLOR_NEUTRAL;
1888
- const H = '#1f1f23';
1889
- return [
1890
- { id: 'amm-airport-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-airport', minzoom: 11, paint: { 'fill-color': C.airport, 'fill-opacity': 0.3 } },
1891
- { id: 'amm-airport-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-airport', minzoom: 11, paint: { 'line-color': '#52525b', 'line-width': 1 } },
1892
- { id: 'amm-runway-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-runway', minzoom: 11, paint: { 'fill-color': C.runway, 'fill-opacity': 1 } },
1893
- { id: 'amm-runway-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-runway', minzoom: 11, paint: { 'line-color': '#52525b', 'line-width': 0.5 } },
1894
- { id: 'amm-apron-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-apron', minzoom: 11, paint: { 'fill-color': C.apron, 'fill-opacity': 1 } },
1895
- { id: 'amm-apron-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-apron', minzoom: 11, paint: { 'line-color': '#3f3f46', 'line-width': 0.5 } },
1896
- { id: 'amm-taxiway-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-taxiway', minzoom: 11, paint: { 'fill-color': C.taxiway, 'fill-opacity': 0.9 } },
1897
- { id: 'amm-taxiway-line', type: 'line', source: sourceId, 'source-layer': 'amm-taxiway-line', minzoom: 11, paint: { 'line-color': C.taxiwayLine, 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 0.8, 18, 2] } },
1898
- {
1899
- id: 'amm-taxiway-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-taxiway-line', minzoom: 14,
1900
- layout: { 'text-field': ['get', 'idlin'], 'text-size': 10, "icon-image": "stretch:text_bg", "icon-text-fit": "both", "icon-text-fit-padding": [1, 2, 1, 2], 'symbol-placement': 'line', 'text-keep-upright': true, 'text-allow-overlap': false },
1901
- paint: { 'text-color': H, "icon-color": C.taxiwayLine },
1902
- },
1903
- { id: 'amm-holding', type: 'line', source: sourceId, 'source-layer': 'amm-holding', minzoom: 11, paint: { 'line-color': C.holding, 'line-width': 1.5 } },
1904
- { id: 'amm-runway-marking', type: 'fill', source: sourceId, 'source-layer': 'amm-runway-marking', minzoom: 13, paint: { 'fill-color': C.runwayMarking, 'fill-opacity': 0.85 } },
1905
- { id: 'amm-restricted-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-restricted', minzoom: 11, paint: { 'fill-color': C.restricted, 'fill-opacity': 0.1 } },
1906
- { id: 'amm-restricted-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-restricted', minzoom: 11, paint: { 'line-color': C.restricted, 'line-width': 1.2, 'line-dasharray': [4, 2] } },
1907
- { id: 'amm-hotspot-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-hotspot', minzoom: 11, paint: { 'fill-color': C.hotspot, 'fill-opacity': 0.12 } },
1908
- { id: 'amm-hotspot-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-hotspot', minzoom: 11, paint: { 'line-color': C.hotspot, 'line-width': 1.2 } },
1909
- { id: 'amm-runway-centerline', type: 'line', source: sourceId, 'source-layer': 'amm-runway-centerline', minzoom: 11, paint: { 'line-color': C.runwayCenterline, 'line-width': 1, 'line-dasharray': [6, 3] } },
1910
- {
1911
- id: 'amm-runway-info', type: 'symbol', source: sourceId, 'source-layer': 'amm-runway-label', minzoom: 13,
1912
- layout: { 'text-field': ['concat', ['coalesce', ['get', 'length'], ''], '×', ['coalesce', ['get', 'width'], ''], 'm'], 'text-size': ['interpolate', ['exponential', 1.5], ['zoom'], 13, 10, 16, 13], 'symbol-placement': 'point', 'text-rotate': ['coalesce', ['get', 'bearing'], 0], 'text-rotation-alignment': 'map', 'text-allow-overlap': true, 'text-ignore-placement': true },
1913
- paint: { 'text-color': '#e4e4e7', 'text-halo-color': H, 'text-halo-width': 2 },
1914
- },
1915
- { id: 'amm-stand-line', type: 'line', source: sourceId, 'source-layer': 'amm-stand-line', minzoom: 13, paint: { 'line-color': C.standLine, 'line-width': 1 } },
1916
- {
1917
- id: 'amm-runway-threshold-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-runway-threshold', minzoom: 12,
1918
- layout: { "icon-image": "stretch:text_bg", "icon-text-fit": "both", "icon-text-fit-padding": [1, 2, 1, 2], 'text-field': ['get', 'idthr'], 'text-size': 14, 'text-allow-overlap': true, 'text-rotation-alignment': 'map', 'icon-rotation-alignment': 'map' },
1919
- paint: { 'text-color': '#ffffff', "icon-color": C.threshold },
1920
- },
1921
- { id: 'amm-stand', type: 'circle', source: sourceId, 'source-layer': 'amm-stand', minzoom: 12, paint: { 'circle-color': C.stand, 'circle-radius': 1.5 } },
1922
- {
1923
- id: 'amm-stand-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-stand', minzoom: 14,
1924
- layout: { 'text-field': ['get', 'idstd'], 'text-size': 9, 'text-anchor': 'bottom', 'text-offset': [0, -0.5], 'text-allow-overlap': false },
1925
- paint: { 'text-color': C.stand, 'text-halo-color': H, 'text-halo-width': 1 },
1926
- },
1927
- { id: 'amm-obstacle-region-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-obstacle-region', minzoom: 11, paint: { 'fill-color': '#fef08a', 'fill-opacity': 0.1 } },
1928
- { id: 'amm-obstacle-region-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-obstacle-region', minzoom: 11, paint: { 'line-color': '#eab308', 'line-width': 1.2, 'line-dasharray': [1.5, 1] } },
1929
- { id: 'amm-obstacle-point', type: 'circle', source: sourceId, 'source-layer': 'amm-obstacle-point', minzoom: 11, paint: { 'circle-color': '#f97316', 'circle-radius': 4, 'circle-stroke-color': H, 'circle-stroke-width': 1 } },
1930
- {
1931
- id: 'amm-obstacle-point-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-obstacle-point', minzoom: 14,
1932
- layout: { 'text-field': ['coalesce', ['get', 'ident'], ['get', 'LABEL']], 'text-size': 9, 'text-anchor': 'bottom', 'text-offset': [0, -0.5], 'text-allow-overlap': false },
1933
- paint: { 'text-color': '#fdba74', 'text-halo-color': H, 'text-halo-width': 1.2 },
1934
- },
1935
- { id: 'amm-construction-fill', type: 'fill', source: sourceId, 'source-layer': 'amm-construction', minzoom: 11, paint: { 'fill-pattern': 'normal:passline', 'fill-opacity': 0.6 } },
1936
- { id: 'amm-construction-stroke', type: 'line', source: sourceId, 'source-layer': 'amm-construction', minzoom: 11, paint: { 'line-color': '#ea580c', 'line-width': 1.2, 'line-dasharray': [4, 2] } },
1937
- {
1938
- id: 'amm-construction-label', type: 'symbol', source: sourceId, 'source-layer': 'amm-construction', minzoom: 13,
1939
- layout: { 'text-field': ['get', 'text'], 'text-size': 9, 'text-anchor': 'center', 'symbol-placement': 'point', 'text-allow-overlap': false },
1940
- paint: { 'text-color': '#f97316', 'text-halo-color': H, 'text-halo-width': 1 },
1941
- },
1942
- ]
2011
+ return buildAMMLayersLight(sourceId, AMM_COLOR_NEUTRAL)
1943
2012
  }
1944
2013
 
1945
2014
  // ── Dispatcher ────────────────────────────────────────────────────────────────
@@ -1955,15 +2024,14 @@ const AMM_LAYER_GROUPS = {
1955
2024
  ammRunway: ['amm-runway-fill', 'amm-runway-stroke', 'amm-runway-info',
1956
2025
  'amm-runway-marking', 'amm-runway-centerline',
1957
2026
  'amm-runway-threshold', 'amm-runway-threshold-label'],
1958
- ammApron: ['amm-apron-fill', 'amm-apron-stroke'],
1959
- ammTaxiway: ['amm-taxiway-fill', 'amm-taxiway-line', 'amm-taxiway-label'],
1960
- ammHolding: ['amm-holding'],
1961
- ammStand: ['amm-stand', 'amm-stand-label', 'amm-stand-line'],
1962
- ammRestricted: ['amm-restricted-fill', 'amm-restricted-stroke'],
1963
- ammHotspot: ['amm-hotspot-fill', 'amm-hotspot-stroke'],
2027
+ ammApron: ['amm-apron-fill', 'amm-apron-label'],
2028
+ ammTaxiway: ['amm-taxiway-fill', 'amm-taxiway-line', 'amm-taxiway-label', 'amm-taxiway-guidanceline', 'amm-taxiway-intersectionline'],
2029
+ ammHolding: ['amm-holding', 'amm-holding-label'],
2030
+ ammStand: ['amm-stand-label', 'amm-stand-line'],
2031
+ ammRestricted: ['amm-restricted-fill'],
2032
+ ammHotspot: ['amm-hotspot-fill'],
1964
2033
  /** 障碍物(点 + 面) */
1965
- ammObstacle: ['amm-obstacle-region-fill', 'amm-obstacle-region-stroke',
1966
- 'amm-obstacle-point', 'amm-obstacle-point-label'],
2034
+ ammObstacle: ['amm-obstacle-region-fill', 'amm-obstacle-point-label'],
1967
2035
  ammConstruction: ['amm-construction-fill', 'amm-construction-stroke', 'amm-construction-label'],
1968
2036
  };
1969
2037
 
@@ -1977,10 +2045,22 @@ const TYPEMAP = {
1977
2045
  ocean: ["ocean_label"],
1978
2046
  airspace: ["airspaceLayer", "airspace_label_side_layer", "airspaceLayer_line", "airspace_label_center_layer"],
1979
2047
  airline: ["airline", "airline_label", "airline_point", "airline_radial"],
1980
- controlled: ["controlledLayer", "controlledLayer_stroke", "controlled_line_label"],
1981
- restricted: ["restrictedLayer", "restrictedLayer_stroke", "restricted_line_label"],
1982
- vor: ["vor_icon", "vor_icon_dial", "vor_label"],
1983
- ndb: ["ndb_icon"],
2048
+ controlled: [
2049
+ "controlledLayer",
2050
+ "controlledLayer_stroke_left_bg",
2051
+ "controlledLayer_stroke_border",
2052
+ "controlledLayer_stroke",
2053
+ "controlled_line_label",
2054
+ ],
2055
+ restricted: [
2056
+ "restrictedLayer",
2057
+ "restrictedLayer_stroke_border",
2058
+ "restrictedLayer_stroke_bg",
2059
+ "restrictedLayer_stroke",
2060
+ "restricted_line_label",
2061
+ ],
2062
+ vor: ["vor_icon", "vor_icon_dial", "vor_label", "vor_label_detail"],
2063
+ ndb: ["ndb_icon", "ndb_label_detail"],
1984
2064
  airport: ["airport", "airport-runway", "airport-runway-cross"],
1985
2065
  adiz: ["adiz-line", "adiz-label"],
1986
2066
  waypointOffAirway: ["waypoint-off-airway-symbol"],
@@ -7451,6 +7531,7 @@ function getAviationBaseStyle(opts) {
7451
7531
  { id: "vor", url: `${spriteBase}/kyresources/sprite-vor` },
7452
7532
  { id: "runway", url: `${spriteBase}/kyresources/sprite-runway` },
7453
7533
  { id: "stretch", url: `${spriteBase}/kyresources/sprite-stretch` },
7534
+ { id: "navig", url: `${spriteBase}/kyresources/sprite-test` },
7454
7535
  ],
7455
7536
  sources: {
7456
7537
  land: { type: "geojson", data: LAND_FC },
@@ -9780,10 +9861,9 @@ const THEME_TOKENS = {
9780
9861
  airspaceStroke: '#6F7E68',
9781
9862
  restrictedFill: '#FAD7A0',
9782
9863
  restrictedFillPattern: "",
9783
- restrictedStrokeLine: '#f6bf65',
9784
- restrictedStroke: '#D35400', // 限制区标注文字色(ICAO 导出/图例用)
9785
- controlledStroke: '#10B981',
9786
- controlledFill: '#10B981',
9864
+ restrictedStrokeLine: '#ca84a0',
9865
+ restrictedStroke: '#ca84a0',
9866
+ controlled: '#5fa4d9',
9787
9867
  segment: '#1C2526',
9788
9868
  segmentWith: ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
9789
9869
  segmentRemark: '#E8A020', // HAS_REMARK 航段
@@ -9792,10 +9872,14 @@ const THEME_TOKENS = {
9792
9872
  airportText: '#006400', // 机场文字色(非 AMM)
9793
9873
  runway: '#006400',
9794
9874
  vorDial: '#0b417a',
9795
- vorNormal: '#3874cb',
9875
+ vorNormal: '#00008B',
9796
9876
  vor: '#00008B',
9877
+ vorCompass: '#2E4053',
9878
+ vorCompassPointer: '#000000',
9797
9879
  ndbIcon: 'v2:ndb-normal', // 图标按主题不同(正常)
9798
9880
  ndb: '#0066CC',
9881
+ navAidDetailText: '#000000',
9882
+ navAidDetailHalo: '#ffffff',
9799
9883
  waypoint: '#1C2526',
9800
9884
  airlinePointIcon: ['case', ['==', ['get', 'report_type'], 'C'], 'waypoint-compusory', 'waypoint'],
9801
9885
  // airline_label format 内嵌文字色
@@ -9820,7 +9904,7 @@ const THEME_TOKENS = {
9820
9904
  restrictedFill: ['case', ['==', ['get', 'CODE_TYPE'], 'P'], '#ef4444', ['==', ['get', 'CODE_TYPE'], 'D'], '#f97316', '#ef4444'],
9821
9905
  restrictedStrokeLine: '#CC7722',
9822
9906
  restrictedStroke: '#CC7722',
9823
- controlledStroke: '#22C55E',
9907
+ controlled: '#22C55E',
9824
9908
  controlledFill: '#22C55E',
9825
9909
  segment: '#40C4FF',
9826
9910
  segmentWith: ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
@@ -9832,8 +9916,12 @@ const THEME_TOKENS = {
9832
9916
  vorDial: '#38bdf8',
9833
9917
  vorNormal: '#38bdf8',
9834
9918
  vor: '#72aae5',
9919
+ vorCompass: '#38bdf8',
9920
+ vorCompassPointer: '#E0F7FA',
9835
9921
  ndbIcon: 'ndb-inway',
9836
9922
  ndb: '#62d6ef',
9923
+ navAidDetailText: '#E0F7FA',
9924
+ navAidDetailHalo: '#0f172a',
9837
9925
  waypoint: '#74cdde',
9838
9926
  airlinePointIcon: ['case', ['==', ['get', 'report_type'], 'C'], 'waypoint-compusory', 'waypoint'],
9839
9927
  alBase: '#0f172a', alDist: '#cbd5e1', alRnp: '#FFFFFF',
@@ -9860,7 +9948,7 @@ const THEME_TOKENS = {
9860
9948
  restrictedFillPattern: "",
9861
9949
  restrictedStrokeLine: '#e59866',
9862
9950
  restrictedStroke: '#e59866',
9863
- controlledStroke: '#52c9a3',
9951
+ controlled: '#52c9a3',
9864
9952
  controlledFill: '#52c9a3',
9865
9953
  segment: '#8fa8c7',
9866
9954
  segmentWith: ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
@@ -9872,8 +9960,12 @@ const THEME_TOKENS = {
9872
9960
  vorDial: '#5dade2',
9873
9961
  vorNormal: '#5dade2',
9874
9962
  vor: '#85a9e0',
9963
+ vorCompass: '#5dade2',
9964
+ vorCompassPointer: '#dce9f0',
9875
9965
  ndbIcon: 'ndb-inway',
9876
9966
  ndb: '#7ec8e3',
9967
+ navAidDetailText: '#dce9f0',
9968
+ navAidDetailHalo: '#16212c',
9877
9969
  waypoint: '#a9c6d8',
9878
9970
  airlinePointIcon: ['case', ['==', ['get', 'report_type'], 'C'], 'waypoint-compusory', 'waypoint'],
9879
9971
  alBase: '#1B2838', alDist: '#b8c9d9', alRnp: '#f4c542',
@@ -9901,7 +9993,7 @@ const THEME_TOKENS = {
9901
9993
  restrictedFillPattern: "",
9902
9994
  restrictedStrokeLine: '#C0392B',
9903
9995
  restrictedStroke: '#C0392B',
9904
- controlledStroke: '#2E5C8A',
9996
+ controlled: '#2E5C8A',
9905
9997
  controlledFill: '#2E5C8A',
9906
9998
  segment: '#34495E',
9907
9999
  segmentWith: ['interpolate', ['linear'], ['zoom'], 6, 0.2, 8, 0.8],
@@ -9913,8 +10005,12 @@ const THEME_TOKENS = {
9913
10005
  vorDial: '#2E5C8A',
9914
10006
  vorNormal: '#2E5C8A',
9915
10007
  vor: '#154360',
10008
+ vorCompass: '#2E5C8A',
10009
+ vorCompassPointer: '#1B2631',
9916
10010
  ndbIcon: 'v2:ndb-normal',
9917
10011
  ndb: '#8B5A2B',
10012
+ navAidDetailText: '#1B2631',
10013
+ navAidDetailHalo: '#F2EFE6',
9918
10014
  waypoint: '#2C3E50',
9919
10015
  airlinePointIcon: ['case', ['==', ['get', 'report_type'], 'C'], 'waypoint-compusory', 'waypoint'],
9920
10016
  alBase: '#F2EFE6', alDist: '#5D6D7E', alRnp: '#D68910',
@@ -9940,7 +10036,7 @@ const THEME_TOKENS = {
9940
10036
  restrictedStrokeLine: '#7E524D',
9941
10037
  restrictedStrokeLineWidth: 1.2,
9942
10038
  restrictedStroke: '#D35400', // 限制区标注文字色(ICAO 导出/图例用)
9943
- controlledStroke: "#88918088",
10039
+ controlled: "#88918088",
9944
10040
  controlledFill: '#C7CEC096',
9945
10041
  segment: '#1C2526',
9946
10042
  segmentWith: ['interpolate', ['linear'], ['zoom'], 6, 1.9, 10, 2.2],
@@ -9952,8 +10048,12 @@ const THEME_TOKENS = {
9952
10048
  vorDial: '#0b417a',
9953
10049
  vorNormal: '#3874cb',
9954
10050
  vor: '#00008B',
10051
+ vorCompass: '#2E4053',
10052
+ vorCompassPointer: '#000000',
9955
10053
  ndbIcon: 'v2:ndb-normal', // 图标按主题不同(正常)
9956
10054
  ndb: '#0066CC',
10055
+ navAidDetailText: '#000000',
10056
+ navAidDetailHalo: '#ffffff',
9957
10057
  waypoint: '#1C2526',
9958
10058
  airlinePointIcon: ['case', ['==', ['get', 'report_type'], 'C'], 'designate_point_inway', 'designate_point_notinway'],
9959
10059
  airlinePointIconSize: 0.65,
@@ -9980,6 +10080,8 @@ const THEME_TOKENS = {
9980
10080
  function buildLayers(themeId = 'light') {
9981
10081
  const T = THEME_TOKENS[themeId] ?? THEME_TOKENS.light;
9982
10082
  const sourceId = 'navdata';
10083
+ const isLightTheme = themeId === 'light';
10084
+ const frutigerBold = ['Frutiger Bold'];
9983
10085
  // `has` alone is insufficient for segment labels: the data can carry an
9984
10086
  // empty direction field. Keep all direction decisions on non-empty values.
9985
10087
  const hasText = (field) => [
@@ -10026,6 +10128,7 @@ function buildLayers(themeId = 'light') {
10026
10128
  ],
10027
10129
  layout: {
10028
10130
  'text-field': ['get', 'name_en'],
10131
+ 'text-font': frutigerBold,
10029
10132
  // zoom 插值必须为顶层表达式;每个档位再乘以按 scalerank 得到的大小倍率
10030
10133
  // (scalerank 0=大洋→最大, 8→最小)。
10031
10134
  'text-size': 11,
@@ -10052,16 +10155,67 @@ function buildLayers(themeId = 'light') {
10052
10155
  },
10053
10156
  {
10054
10157
  id: 'airspace_label_side_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir', minzoom: 4,
10055
- 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 },
10158
+ layout: { 'text-field': ["concat", ["get", "TXT_NAME"], "/", ["get", "CODE_ID"], "/", ["get", "CODE_TYPE"]], 'text-font': frutigerBold, 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1], "text-letter-spacing": 0.05, "text-optional": true },
10056
10159
  paint: { 'text-color': T.airspaceStroke, ...T.sideHalo },
10057
10160
  },
10058
10161
  {
10059
- id: 'airspace_label_center_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir-centroid', minzoom: 3,
10162
+ id: 'airspace_label_center_layer', type: 'symbol', source: sourceId, 'source-layer': 'fir-centroid',
10163
+ minzoom: 3,
10164
+ "maxzoom": 6,
10060
10165
  layout: {
10061
- 'text-field': ['coalesce', ['get', 'CODE_ID'], ['get', 'TXT_NAME']],
10062
- 'text-size': ['interpolate', ['linear'], ['zoom'], 3, 12, 17, 16],
10166
+ 'text-field': '{CODE_ID}',
10167
+ 'text-font': frutigerBold,
10063
10168
  'symbol-placement': 'point',
10064
10169
  'text-max-width': 8,
10170
+ 'symbol-sort-key': ['*', -1, ['get', 'SIZE']],
10171
+ "text-letter-spacing": 0.02,
10172
+ "text-size": [
10173
+ "interpolate",
10174
+ ["linear"],
10175
+ ["zoom"],
10176
+
10177
+ // Z2:全球视角
10178
+ 2,
10179
+ [
10180
+ "interpolate",
10181
+ ["linear"],
10182
+ ["sqrt", ["get", "SIZE"]],
10183
+ 100, 9,
10184
+ 316, 11,
10185
+ 707, 13,
10186
+ 1000, 14,
10187
+ 1414, 16,
10188
+ 2236, 18
10189
+ ],
10190
+
10191
+ // Z4:区域视角
10192
+ 4,
10193
+ [
10194
+ "interpolate",
10195
+ ["linear"],
10196
+ ["sqrt", ["get", "SIZE"]],
10197
+ 100, 10,
10198
+ 316, 12,
10199
+ 707, 14,
10200
+ 1000, 16,
10201
+ 1414, 18,
10202
+ 2236, 20
10203
+ ],
10204
+
10205
+ // Z6:FIR 最后显示层级
10206
+ 6,
10207
+ [
10208
+ "interpolate",
10209
+ ["linear"],
10210
+ ["sqrt", ["get", "SIZE"]],
10211
+ 100, 11,
10212
+ 316, 13,
10213
+ 707, 15,
10214
+ 1000, 17,
10215
+ 1414, 19,
10216
+ 2236, 21
10217
+ ]
10218
+ ]
10065
10219
  },
10066
10220
  paint: {
10067
10221
  'text-color': T.airspaceStroke,
@@ -10077,14 +10231,57 @@ function buildLayers(themeId = 'light') {
10077
10231
  'fill-opacity': ["interpolate", ["linear"], ["zoom"], 10, 0.15, 11.5, 0],
10078
10232
  },
10079
10233
  },
10234
+ {
10235
+ id: 'restrictedLayer_stroke_bg', type: 'line', source: sourceId, 'source-layer': 'restricted',
10236
+ paint: {
10237
+ 'line-color': T.restrictedStrokeLine,
10238
+ 'line-opacity': isLightTheme ? ['step', ['zoom'], 0, 6, 0.2] : 0,
10239
+ 'line-offset': ['interpolate', ['exponential', 2], ['zoom'], 6, 1, 7, 1, 10, 5],
10240
+ 'line-width': ['interpolate', ['exponential', 2], ['zoom'], 6, 1, 7, 2, 10, 10],
10241
+ },
10242
+ },
10080
10243
  {
10081
10244
  id: 'restrictedLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'restricted',
10082
- paint: { 'line-color': T.restrictedStrokeLine, 'line-width': T.restrictedStrokeLineWidth || 1, "line-dasharray": [2, 2], "line-opacity": ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1] },
10245
+ layout: isLightTheme
10246
+ ? { 'line-join': 'round', 'line-cap': 'round' }
10247
+ : {},
10248
+ paint: isLightTheme
10249
+ ? {
10250
+ 'line-color': T.restrictedStrokeLine,
10251
+ 'line-opacity': ['step', ['zoom'], 0, 6, 1],
10252
+ 'line-width': ['interpolate', ['exponential', 2], ['zoom'], 6, 0.5, 7, 1, 8, 2],
10253
+ }
10254
+ : {
10255
+ 'line-color': T.restrictedStrokeLine,
10256
+ 'line-width': T.restrictedStrokeLineWidth || 1,
10257
+ 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1],
10258
+ },
10083
10259
  },
10084
10260
  {
10085
10261
  id: 'restricted_line_label', type: 'symbol', source: sourceId, 'source-layer': 'restricted', minzoom: 6,
10086
- 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] },
10087
- paint: { 'text-color': T.restrictedStroke, ...T.restrictedHalo },
10262
+ layout: {
10263
+ 'text-field': [
10264
+ 'concat',
10265
+ ['get', 'TXT_NAME'],
10266
+ ':',
10267
+ [
10268
+ 'case',
10269
+ ['==', ['get', 'alt_lower'], 0],
10270
+ 'GND',
10271
+ ['to-string', ['get', 'alt_lower']]
10272
+ ],
10273
+ '-',
10274
+ [
10275
+ 'case',
10276
+ ['==', ['get', 'alt_upper'], 99999],
10277
+ 'UNL',
10278
+ ['to-string', ['get', 'alt_upper']]
10279
+ ]
10280
+ ], 'text-font': frutigerBold, "text-letter-spacing": 0.1, 'text-size': 10, 'symbol-placement': 'line', 'text-max-width': 8, "text-offset": [0, 1.5]
10281
+ },
10282
+ paint: isLightTheme
10283
+ ? { 'text-color': T.restrictedStroke, 'text-halo-color': T.halo, 'text-halo-width': 0.5 }
10284
+ : { 'text-color': T.restrictedStroke, ...T.restrictedHalo },
10088
10285
  },
10089
10286
  {
10090
10287
  id: 'controlledLayer', type: 'fill', source: sourceId, 'source-layer': 'controlled-fill', minzoom: 4,
@@ -10093,14 +10290,60 @@ function buildLayers(themeId = 'light') {
10093
10290
  "fill-opacity": ["interpolate", ["linear"], ["zoom"], 10, 0.035, 11.5, 0],
10094
10291
  },
10095
10292
  },
10293
+ {
10294
+ // Based on Navigraph's controlled-airspace treatment. The current
10295
+ // navdata stack calls this source-layer `controlled`; no `lo` filter is
10296
+ // applied so all controlled-airspace features remain visible.
10297
+ id: 'controlledLayer_stroke_left_bg', type: 'line', source: sourceId, 'source-layer': 'controlled',
10298
+ paint: {
10299
+ 'line-color': T.controlled,
10300
+ 'line-opacity': isLightTheme ? ['step', ['zoom'], 0, 6, 0.2] : 0,
10301
+ 'line-offset': ['interpolate', ['exponential', 2], ['zoom'], 6, 0, 7, 1, 10, 5],
10302
+ 'line-width': ['interpolate', ['exponential', 2], ['zoom'], 6, 1, 7, 2, 10, 10],
10303
+ },
10304
+ },
10096
10305
  {
10097
10306
  id: 'controlledLayer_stroke', type: 'line', source: sourceId, 'source-layer': 'controlled',
10098
- paint: { 'line-color': T.controlledStroke, 'line-width': 1, 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1], "line-dasharray": [1, 1.4] },
10307
+ layout: isLightTheme
10308
+ ? { 'line-join': 'round', 'line-cap': 'square' }
10309
+ : {},
10310
+ paint: isLightTheme
10311
+ ? {
10312
+ 'line-color': T.controlled,
10313
+ 'line-dasharray': [2, 2, 4, 2],
10314
+ 'line-opacity': ['interpolate', ['linear'], ['zoom'], 6, 0, 6.5, 1],
10315
+ 'line-width': 1,
10316
+ }
10317
+ : {
10318
+ 'line-color': T.controlled,
10319
+ 'line-width': 1,
10320
+ 'line-opacity': ['interpolate', ['linear'], ['zoom'], 4, 0.5, 8, 1],
10321
+ 'line-dasharray': [1, 1.4],
10322
+ },
10099
10323
  },
10100
10324
  {
10101
10325
  id: 'controlled_line_label', type: 'symbol', source: sourceId, 'source-layer': 'controlled', minzoom: 6,
10102
- 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] },
10103
- paint: { 'text-color': T.controlledStroke, ...T.controlledHalo },
10326
+ layout: {
10327
+ 'text-field': [
10328
+ 'concat',
10329
+ ['get', 'TXT_NAME'],
10330
+ ':',
10331
+ [
10332
+ 'case',
10333
+ ['==', ['get', 'alt_lower'], 0],
10334
+ 'GND',
10335
+ ['to-string', ['get', 'alt_lower']]
10336
+ ],
10337
+ '-',
10338
+ [
10339
+ 'case',
10340
+ ['==', ['get', 'alt_upper'], 99999],
10341
+ 'UNL',
10342
+ ['to-string', ['get', 'alt_upper']]
10343
+ ]
10344
+ ], 'text-font': frutigerBold, 'text-size': 10, 'symbol-placement': 'line', 'text-letter-spacing': 0.2, 'text-max-width': 8, "text-offset": [0, 1.5]
10345
+ },
10346
+ paint: { 'text-color': T.controlled, ...T.controlledHalo },
10104
10347
  },
10105
10348
  {
10106
10349
  id: 'airline', type: 'line', source: sourceId, 'source-layer': 'segment', minzoom: 6,
@@ -10111,13 +10354,64 @@ function buildLayers(themeId = 'light') {
10111
10354
  "line-opacity": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 7, 1, 8, 1, 12, 0.8, 15, 0.2],
10112
10355
  }
10113
10356
  },
10357
+ {
10358
+ "id": "airline-shadow",
10359
+ "type": "line",
10360
+ "source": sourceId,
10361
+ "source-layer": "segment-shdow",
10362
+ "minzoom": 6,
10363
+ "layout": {
10364
+ "line-cap": "round",
10365
+ "line-join": "round"
10366
+ },
10367
+ "paint": {
10368
+ "line-color": T.segment,
10369
+ "line-width": {
10370
+ "base": 2,
10371
+ "stops": [
10372
+ [
10373
+ 3,
10374
+ 0.1
10375
+ ],
10376
+ [
10377
+ 8,
10378
+ 1
10379
+ ]
10380
+ ]
10381
+ },
10382
+ "line-dasharray": [
10383
+ 2,
10384
+ 2
10385
+ ],
10386
+ "line-opacity": {
10387
+ "base": 2,
10388
+ "stops": [
10389
+ [
10390
+ 5,
10391
+ 0.125
10392
+ ],
10393
+ [
10394
+ 8,
10395
+ 0.2
10396
+ ]
10397
+ ]
10398
+ }
10399
+ },
10400
+ },
10114
10401
  {
10115
10402
  id: 'airline_label', type: 'symbol', source: sourceId, 'source-layer': 'segment', minzoom: 6,
10116
10403
  layout: {
10117
- "icon-image": ["case", hasBothDesignation, "stretch:segment-both", hasForwardDesignation, "stretch:segment-right", hasBackwardDesignation, "stretch:segment-left", "stretch:segment-both"],
10404
+ "icon-image": [
10405
+ 'match',
10406
+ ['get', 'DIRECTION'],
10407
+ 'FORWARD', 'stretch:segment-right',
10408
+ 'BACKWARD', 'stretch:segment-left',
10409
+ 'stretch:segment-both',
10410
+ ],
10118
10411
  "icon-anchor": "center", "symbol-placement": "line", "icon-text-fit": "width", "icon-size": 1,
10119
10412
  "text-allow-overlap": false, "icon-allow-overlap": false, "text-optional": false,
10120
10413
  "text-anchor": "center", "text-justify": "center", "text-line-height": 1.3, "text-letter-spacing": 0.1,
10414
+ "text-font": ['Frutiger Regular'],
10121
10415
  "text-field": ["step", ["zoom"],
10122
10416
  ["format", ["case", hasBothDesignation, ["get", "TXT_DESIG"], hasForwardDesignation, ["get", "TXT_DESIG_FORWARD"], hasBackwardDesignation, ["get", "TXT_DESIG_BACKWARD"], "-"], { "font-scale": 1, "text-color": T.alBase }],
10123
10417
  10,
@@ -10143,21 +10437,88 @@ function buildLayers(themeId = 'light') {
10143
10437
  },
10144
10438
  },
10145
10439
  {
10146
- id: 'airline_radial', type: 'symbol', source: sourceId, 'source-layer': 'segment-radial', minzoom: 13,
10147
- layout: {
10148
- 'text-field': ['concat', ['get', 'bearing'], '°'],
10149
- 'text-size': 9,
10150
- 'text-rotate': ['to-number', ['get', 'line_angle'], 0],
10151
- 'text-rotation-alignment': 'map',
10152
- 'text-allow-overlap': true,
10153
- 'text-ignore-placement': true,
10154
- 'text-offset': [0, -0.6],
10155
- 'text-justify': 'auto',
10440
+ id: 'airline_radial', type: 'symbol', source: sourceId, 'source-layer': 'segment-radial', minzoom: 11,
10441
+ "layout": {
10442
+ "text-rotation-alignment": "map",
10443
+ "text-line-height": 0.5,
10444
+ "text-font": [
10445
+ "Font11"
10446
+ ],
10447
+ "text-padding": 1,
10448
+ "text-size": {
10449
+ "base": 2,
10450
+ "stops": [
10451
+ [
10452
+ 8,
10453
+ 6
10454
+ ],
10455
+ [
10456
+ 10,
10457
+ 8
10458
+ ]
10459
+ ]
10460
+ },
10461
+ "symbol-placement": "line-center",
10462
+ "text-field": [
10463
+ "concat",
10464
+ [
10465
+ "case",
10466
+ [
10467
+ "<",
10468
+ [
10469
+ "to-number",
10470
+ [
10471
+ "get",
10472
+ "bearing"
10473
+ ]
10474
+ ],
10475
+ 10
10476
+ ],
10477
+ "00",
10478
+ [
10479
+ "case",
10480
+ [
10481
+ "<",
10482
+ [
10483
+ "to-number",
10484
+ [
10485
+ "get",
10486
+ "bearing"
10487
+ ]
10488
+ ],
10489
+ 100
10490
+ ],
10491
+ "0",
10492
+ ""
10493
+ ]
10494
+ ],
10495
+ [
10496
+ "get",
10497
+ "bearing"
10498
+ ],
10499
+ "^"
10500
+ ]
10501
+ },
10502
+ "paint": {
10503
+ "text-color": T.segment,
10504
+ "text-halo-color": T.halo,
10505
+ "text-halo-width": {
10506
+ "base": 2,
10507
+ "stops": [
10508
+ [
10509
+ 8,
10510
+ 0.8
10511
+ ],
10512
+ [
10513
+ 10,
10514
+ 1.2
10515
+ ]
10516
+ ]
10517
+ }
10156
10518
  },
10157
- paint: { 'text-color': T.segment, ...T.radialHalo },
10158
10519
  },
10159
10520
  {
10160
- id: 'airport', type: 'symbol', source: sourceId, minzoom: 2, 'source-layer': 'airport',
10521
+ id: 'airport', type: 'symbol', source: sourceId, minzoom: 2.5, 'source-layer': 'airport',
10161
10522
  // 4级前就显示大型机场+中型,5级后全部显示
10162
10523
  filter:
10163
10524
  ['case',
@@ -10187,7 +10548,7 @@ function buildLayers(themeId = 'light') {
10187
10548
  "text-optional": true,
10188
10549
  "visibility": "none",
10189
10550
  "icon-size": ["interpolate", ["linear"], ["zoom"], 2, 0.6, 5, 0.7, 9, 1, 12, 1.1],
10190
- 'text-font': ['Open Sans Semibold'],
10551
+ 'text-font': frutigerBold,
10191
10552
  },
10192
10553
  paint: {
10193
10554
  'icon-color': ['case', ['has', 'has_amm'], T.airportamm, T.airport],
@@ -10274,9 +10635,22 @@ function buildLayers(themeId = 'light') {
10274
10635
  },
10275
10636
  {
10276
10637
  id: 'vor_icon_dial', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 8,
10638
+ 'maxzoom': 12,
10277
10639
  layout: {
10278
- "icon-image": "vor:vor_dial",
10279
- "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],
10640
+ "icon-image": "navig:compass",
10641
+ "icon-size": {
10642
+ "base": 2,
10643
+ "stops": [
10644
+ [
10645
+ 8,
10646
+ 0.0625
10647
+ ],
10648
+ [
10649
+ 12,
10650
+ 1
10651
+ ]
10652
+ ]
10653
+ },
10280
10654
  "icon-rotate": ["to-number", ["get", "VAL_MAG_VAR"], 0],
10281
10655
  "icon-rotation-alignment": "map",
10282
10656
  "symbol-z-order": "viewport-y",
@@ -10288,10 +10662,140 @@ function buildLayers(themeId = 'light') {
10288
10662
  paint: { "icon-color": T.vorDial }
10289
10663
  },
10290
10664
  {
10291
- id: 'vor_icon', minzoom: 4, maxzoom: 9, type: 'symbol', source: sourceId, 'source-layer': 'vor',
10665
+ "id": "vor_icon_dial_arrow",
10666
+ "type": "symbol",
10667
+ "source": sourceId,
10668
+ "source-layer": 'vor',
10669
+ "minzoom": 8.5,
10670
+ 'maxzoom': 12,
10671
+ "layout": {
10672
+ "icon-rotation-alignment": "map",
10673
+ "icon-allow-overlap": true,
10674
+ "icon-image": "navig:compass-arrow",
10675
+ "icon-rotate": ["to-number", ["get", "VAL_MAG_VAR"], 0],
10676
+ "icon-size": {
10677
+ "base": 2,
10678
+ "stops": [
10679
+ [
10680
+ 8,
10681
+ 0.0625
10682
+ ],
10683
+ [
10684
+ 12,
10685
+ 1
10686
+ ]
10687
+ ]
10688
+ }
10689
+ },
10690
+ "paint": {
10691
+ "icon-color": T.vorDial
10692
+ }
10693
+ },
10694
+ {
10695
+ "id": "vor-compass-ring",
10696
+ "type": "line",
10697
+ "source": sourceId,
10698
+ "source-layer": "compass",
10699
+ "minzoom": 12.1,
10700
+ "filter": [
10701
+ "==",
10702
+ [
10703
+ "get",
10704
+ "kind"
10705
+ ],
10706
+ "ring"
10707
+ ],
10708
+ "layout": {
10709
+ "line-cap": "round",
10710
+ "line-join": "round",
10711
+ "visibility": "visible"
10712
+ },
10713
+ "paint": {
10714
+ "line-color": T.vorDial,
10715
+ "line-width": 1.15,
10716
+ "line-opacity": 0.9
10717
+ }
10718
+ },
10719
+ {
10720
+ "id": "vor-compass-ticks",
10721
+ "type": "line",
10722
+ "source": sourceId,
10723
+ "source-layer": "compass",
10724
+ "minzoom": 12.1,
10725
+ "filter": [
10726
+ "==",
10727
+ [
10728
+ "get",
10729
+ "kind"
10730
+ ],
10731
+ "ticks"
10732
+ ],
10733
+ "layout": {
10734
+ "line-cap": "round",
10735
+ "line-join": "round",
10736
+ "visibility": "visible"
10737
+ },
10738
+ "paint": {
10739
+ "line-color": T.vorDial,
10740
+ "line-width": [
10741
+ "match",
10742
+ [
10743
+ "get",
10744
+ "rank"
10745
+ ],
10746
+ "cardinal",
10747
+ 1.7,
10748
+ "major",
10749
+ 1.4,
10750
+ "medium",
10751
+ 1.2,
10752
+ 1
10753
+ ],
10754
+ "line-opacity": 0.9
10755
+ }
10756
+ },
10757
+ {
10758
+ "id": "vor-compass-pointer",
10759
+ "type": "line",
10760
+ "source": sourceId,
10761
+ "source-layer": "compass",
10762
+ "minzoom": 12.1,
10763
+ "filter": [
10764
+ "==",
10765
+ [
10766
+ "get",
10767
+ "kind"
10768
+ ],
10769
+ "pointer"
10770
+ ],
10771
+ "layout": {
10772
+ "line-cap": "round",
10773
+ "line-join": "round",
10774
+ "visibility": "visible"
10775
+ },
10776
+ "paint": {
10777
+ "line-color": T.vorDial,
10778
+ "line-width": 1.8,
10779
+ "line-opacity": 1
10780
+ }
10781
+ },
10782
+ {
10783
+ id: 'vor_icon', minzoom: 4, type: 'symbol', source: sourceId, 'source-layer': 'vor',
10292
10784
  layout: {
10293
- "icon-image": "v2:vor-normal",
10294
- "icon-size": ["interpolate", ["linear"], ["zoom"], 4, 0.7, 8, 1],
10785
+ "icon-image": "navig:vordme",
10786
+ "icon-size": {
10787
+ "base": 2,
10788
+ "stops": [
10789
+ [
10790
+ 5,
10791
+ 0.4
10792
+ ],
10793
+ [
10794
+ 7,
10795
+ 0.5
10796
+ ]
10797
+ ]
10798
+ },
10295
10799
  "icon-rotation-alignment": "map",
10296
10800
  "symbol-z-order": "viewport-y",
10297
10801
  "text-letter-spacing": 0.05,
@@ -10300,13 +10804,40 @@ function buildLayers(themeId = 'light') {
10300
10804
  },
10301
10805
  paint: {
10302
10806
  "icon-color": T.vorNormal,
10303
- "icon-opacity": ["interpolate", ["linear"], ["zoom"], 8, 1, 9, 0],
10807
+ "icon-halo-color": "#fff",
10808
+ 'icon-opacity': 1,
10809
+ "icon-halo-width": {
10810
+ "base": 2,
10811
+ "stops": [
10812
+ [
10813
+ 5,
10814
+ 0.5
10815
+ ],
10816
+ [
10817
+ 7,
10818
+ 1
10819
+ ]
10820
+ ]
10821
+ },
10822
+ "icon-halo-blur": {
10823
+ "base": 2,
10824
+ "stops": [
10825
+ [
10826
+ 5,
10827
+ 0.5
10828
+ ],
10829
+ [
10830
+ 7,
10831
+ 1
10832
+ ]
10833
+ ]
10834
+ }
10304
10835
  }
10305
10836
  },
10306
10837
  {
10307
- id: 'vor_label', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 5,
10838
+ id: 'vor_label', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 5, maxzoom: 8,
10308
10839
  layout: {
10309
- 'text-field': ['get', 'CODE_ID'], 'text-size': 10, 'text-anchor': 'top',
10840
+ 'text-field': ['get', 'CODE_ID'], 'text-font': ['Frutiger Regular'], 'text-size': 10, 'text-anchor': 'top',
10310
10841
  'text-offset': [0, 0.8]
10311
10842
  },
10312
10843
  paint: { 'text-color': T.vor, 'text-halo-color': T.halo, 'text-halo-width': 1 },
@@ -10316,12 +10847,8 @@ function buildLayers(themeId = 'light') {
10316
10847
  layout: {
10317
10848
  "icon-image": T.ndbIcon, "icon-size": ["interpolate", ["linear"], ["zoom"], 6, 0.5, 10, 1],
10318
10849
  "symbol-z-order": "viewport-y",
10319
- "text-field": [
10320
- "format",
10321
- ["get", "CODE_ID"], { "text-color": T.ndb, "font-scale": 1.1 },
10322
- "", {},
10323
- ["coalesce", ["get", "VAL_FREQ"], ""], { "text-color": T.ndb, "font-scale": 0.95 }
10324
- ],
10850
+ "text-font": frutigerBold,
10851
+ "text-field": ["get", "CODE_ID"],
10325
10852
  "text-size": 10,
10326
10853
  "text-offset": [0, 0.5],
10327
10854
  "text-letter-spacing": 0.05,
@@ -10333,10 +10860,67 @@ function buildLayers(themeId = 'light') {
10333
10860
  "text-color": T.ndb,
10334
10861
  ...T.ndbHalo,
10335
10862
  "icon-color": T.ndb,
10336
- "text-opacity": ["interpolate", ["linear"], ["zoom"], 4, 0, 5.5, 0, 6, 0.6, 8, 1, 10, 0.3],
10863
+ "text-opacity": ["step", ["zoom"], 0, 5.5, 0, 6, 0.6, 7, 1, 8, 0],
10337
10864
  "icon-opacity": ["interpolate", ["linear"], ["zoom"], 4, 0, 5, 0.3, 5.5, 0.8, 8, 1, 12, 1, 14, 0.6],
10338
10865
  }
10339
10866
  },
10867
+ {
10868
+ id: 'vor_label_detail', type: 'symbol', source: sourceId, 'source-layer': 'vor', minzoom: 8,
10869
+ layout: {
10870
+ 'text-max-width': 20,
10871
+ 'text-allow-overlap': false,
10872
+ 'text-size': ['interpolate', ['exponential', 2], ['zoom'], 5, 6, 7, 10.5],
10873
+ 'text-radial-offset': 1,
10874
+ 'text-justify': 'auto',
10875
+ 'text-variable-anchor': ['bottom', 'right', 'left', 'top', 'bottom-right', 'bottom-left', 'top-right', 'top-left'],
10876
+ 'text-font': ['Fira Code SemiBold'],
10877
+ 'text-padding': 8,
10878
+ 'text-line-height': 0.2,
10879
+ 'text-field': [
10880
+ 'case',
10881
+ ['==', ['get', 'VAL_FREQ'], 0],
10882
+ ['get', 'CODE_ID'],
10883
+ ['format',
10884
+ ['get', 'TXT_NAME'], { 'font-scale': 0.8 },
10885
+ '\n\n\n\n\n\n', {},
10886
+ ['get', 'CODE_ID'], { 'font-scale': 1.5, 'text-font': ['literal', ['Morse']] },
10887
+ '\n', {},
10888
+ ['concat',
10889
+ ['case', ['==', ['get', 'ARINC'], ''], '', ['concat', ' ', ['get', 'ARINC'], ' ']],
10890
+ ['get', 'VAL_FREQ'], ' ', ['get', 'CODE_ID'],
10891
+ ], {},
10892
+ ],
10893
+ ],
10894
+ },
10895
+ paint: { 'text-color': T.navAidDetailText, 'text-halo-color': T.navAidDetailHalo, 'text-halo-width': 0.2 },
10896
+ },
10897
+ {
10898
+ id: 'ndb_label_detail', type: 'symbol', source: sourceId, 'source-layer': 'ndb', minzoom: 8,
10899
+ layout: {
10900
+ 'text-max-width': 20,
10901
+ 'text-allow-overlap': false,
10902
+ 'text-size': ['interpolate', ['exponential', 2], ['zoom'], 5, 6, 7, 10.5],
10903
+ 'text-radial-offset': 1,
10904
+ 'text-justify': 'auto',
10905
+ 'text-variable-anchor': ['bottom', 'right', 'left', 'top', 'bottom-right', 'bottom-left', 'top-right', 'top-left'],
10906
+ 'text-font': ['Fira Code SemiBold'],
10907
+ 'text-padding': 8,
10908
+ 'text-line-height': 0.2,
10909
+ 'text-field': [
10910
+ 'case',
10911
+ ['==', ['get', 'VAL_FREQ'], 0],
10912
+ ['get', 'CODE_ID'],
10913
+ ['format',
10914
+ ['get', 'TXT_NAME'], { 'font-scale': 0.8 },
10915
+ '\n\n\n\n\n\n', {},
10916
+ ['get', 'CODE_ID'], { 'font-scale': 1.5, 'text-font': ['literal', ['Morse']] },
10917
+ '\n', {},
10918
+ ['get', 'VAL_FREQ'], ' ', ['get', 'CODE_ID'], {},
10919
+ ],
10920
+ ],
10921
+ },
10922
+ paint: { 'text-color': T.navAidDetailText, 'text-halo-color': T.navAidDetailHalo, 'text-halo-width': 0.2 },
10923
+ },
10340
10924
  {
10341
10925
  id: 'airline_point', type: 'symbol', source: sourceId, 'source-layer': 'waypoint', minzoom: 6,
10342
10926
  layout: {
@@ -10349,7 +10933,7 @@ function buildLayers(themeId = 'light') {
10349
10933
  "text-letter-spacing": 0.02,
10350
10934
  '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]],
10351
10935
  'text-justify': 'auto',
10352
- 'text-font': ['Open Sans Semibold']
10936
+ 'text-font': frutigerBold
10353
10937
  },
10354
10938
  paint: {
10355
10939
  'icon-color': T.waypoint,
@@ -10365,7 +10949,7 @@ function buildLayers(themeId = 'light') {
10365
10949
  },
10366
10950
  {
10367
10951
  id: 'waypoint-off-airway-symbol', type: 'symbol', source: sourceId, 'source-layer': 'waypoint-off-airway', minzoom: 7,
10368
- 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 },
10952
+ 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-font': frutigerBold, '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 },
10369
10953
  paint: {
10370
10954
  'icon-color': T.waypoint, 'text-color': T.waypoint, 'text-halo-color': T.halo, 'text-halo-width': 1,
10371
10955
  "icon-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0.5, 12, 1, 15, 0.2],
@@ -10389,12 +10973,24 @@ const CHART_THEMES = {
10389
10973
  const LAYER_GROUPS = {
10390
10974
  adiz: ['adiz-line', 'adiz-label'],
10391
10975
  airspace: ['airspaceLayer', 'airspaceLayer_line', 'airspace_label_center_layer', 'airspace_label_side_layer'],
10392
- restricted: ['restrictedLayer', 'restrictedLayer_stroke', 'restricted_line_label'],
10393
- controlled: ['controlledLayer', 'controlledLayer_stroke', 'controlled_line_label'],
10394
- airline: ['airline_radial', 'airline', 'airline_label', 'airline_point'],
10976
+ restricted: [
10977
+ 'restrictedLayer',
10978
+ 'restrictedLayer_stroke_border',
10979
+ 'restrictedLayer_stroke_bg',
10980
+ 'restrictedLayer_stroke',
10981
+ 'restricted_line_label',
10982
+ ],
10983
+ controlled: [
10984
+ 'controlledLayer',
10985
+ 'controlledLayer_stroke_left_bg',
10986
+ 'controlledLayer_stroke_border',
10987
+ 'controlledLayer_stroke',
10988
+ 'controlled_line_label',
10989
+ ],
10990
+ airline: ['airline_radial', 'airline', 'airline-shadow', 'airline_label', 'airline_point'],
10395
10991
  waypointOffAirway: ['waypoint-off-airway-symbol'],
10396
- vor: ['vor_icon_dial', 'vor_label', 'vor_icon'],
10397
- ndb: ['ndb_icon'],
10992
+ vor: ['vor_icon_dial', 'vor_icon_dial_arrow', 'vor_label', 'vor_label_detail', 'vor_icon'],
10993
+ ndb: ['ndb_icon', 'ndb_label_detail'],
10398
10994
  airport: ['airport', 'airport-runway', 'airport-runway-cross'],
10399
10995
  };
10400
10996