基于Martin的全国基础底图实现

news2025/2/23 11:55:22

概述

前面有文章基于Martin实现MapboxGL自定义底图分享了Martin的使用,本文使用网络收集的数据实现了全国基础数据的收集和基础底图。

实现后效果

全图效果

不确定国界

局部细节

铁路

建筑物

放大后三维效果

实现

1. 数据准备

实例中包含如下数据:

  • 边界线和九段线数据
  • 省边界面数据
  • 省会城市点数据
  • 市边界面数据
  • 市中心点数据
  • 区边界面数据
  • 区中心点数据
  • 建筑物数据
  • 河流(1级、2级和5级)
  • 铁路数据
  • 公路数据
  • 机场数据

2. 数据入库

将准备好的数据导入的数据库中。

  • 可借助QGIS实现,操作步骤可参考教程QGIS工具箱导入。
  • 或借助工具PostGIS PostGIS Bundle 3 for PostgreSQL x64 12 Shapefile and DBF Loader Exporter导入到数据库中。可参考教程数据的导入
  • 或下载我分享的数据库备份文件还原

3. 修改配置文件

martin.exe同级目录下新建文件config.yaml,内容如下:

# Connection keep alive timeout [default: 75]
keep_alive: 75

# The socket address to bind [default: 0.0.0.0:3000]
listen_addresses: '0.0.0.0:3000'

# Set TileJSON URL path prefix. This overides the default of respecting the X-Rewrite-URL header.
# Only modifies the JSON (TileJSON) returned, martins' API-URLs remain unchanged. If you need to rewrite URLs, please use a reverse proxy.
# Must begin with a `/`.
# Examples: `/`, `/tiles`
base_path: /tiles

# Number of web server workers
worker_processes: 16

# Amount of memory (in MB) to use for caching tiles [default: 512, 0 to disable]
cache_size_mb: 50000

# If the client accepts multiple compression formats, and the tile source is not pre-compressed, which compression should be used. `gzip` is faster, but `brotli` is smaller, and may be faster with caching.  Default could be different depending on Martin version.
preferred_encoding: gzip

# Enable or disable Martin web UI. At the moment, only allows `enable-for-all` which enables the web UI for all connections. This may be undesirable in a production environment. [default: disable]
web_ui: enable

# Database configuration. This can also be a list of PG configs.
postgres:
  # Database connection string. You can use env vars too, for example:
  #   $DATABASE_URL
  #   ${DATABASE_URL:-postgresql://postgres@localhost/db} 'postgres://<database_username>:<database_userpassword>@<hostaddress>:<port_no>/<database_name>'
  connection_string: 'postgresql://postgres:root@localhost:5432/lzugis'

  #  If a spatial table has SRID 0, then this SRID will be used as a fallback
  default_srid: 4326

  # Maximum Postgres connections pool size [default: 20]
  pool_size: 20

  # Limit the number of table geo features included in a tile. Unlimited by default.
  # max_feature_count: 1000

  # Control the automatic generation of bounds for spatial tables [default: quick]
  # 'calc' - compute table geometry bounds on startup.
  # 'quick' - same as 'calc', but the calculation will be aborted if it takes more than 5 seconds.
  # 'skip' - do not compute table geometry bounds on startup.
  auto_bounds: skip

  # Enable automatic discovery of tables and functions.
  # You may set this to `false` to disable.
  auto_publish:
    # Optionally limit to just these schemas
    from_schemas:
      - public
    # Here we enable both tables and functions auto discovery.
    # You can also enable just one of them by not mentioning the other,
    # or setting it to false.  Setting one to true disables the other one as well.
    # E.g. `tables: false` enables just the functions auto-discovery.
    tables:
      # Optionally set how source ID should be generated based on the table's name, schema, and geometry column
      source_id_format: '{table}'
      # Add more schemas to the ones listed above
      # A table column to use as the feature ID
      # If a table has no column with this name, `id_column` will not be set for that table.
      # If a list of strings is given, the first found column will be treated as a feature ID.
      id_columns: gid
      # Boolean to control if geometries should be clipped or encoded as is, optional, default to true
      clip_geom: true
      # Buffer distance in tile coordinate space to optionally clip geometries, optional, default to 64
      buffer: 64
      # Tile extent in tile coordinate space, optional, default to 4096
      extent: 4096
    functions:
      # Optionally set how source ID should be generated based on the function's name and schema
      source_id_format: '{schema}.{function}'

  # Associative arrays of table sources
  tables:
    table_source_id:
      # ID of the MVT layer (optional, defaults to table name)
      layer_id: my_base

      # Table schema (required)
      schema: public

      # Table name (required)
      table: province,capital,city

      # Geometry SRID (required)
      srid: 4326

      # Geometry column name (required)
      geometry_column: geom

      # Feature id column name
      id_column: ~

      # An integer specifying the minimum zoom level
      minzoom: 0

      # An integer specifying the maximum zoom level. MUST be >= minzoom
      maxzoom: 10

      # The maximum extent of available map tiles. Bounds MUST define an area
      # covered by all zoom levels. The bounds are represented in WGS:84
      # latitude and longitude values, in the order left, bottom, right, top.
      # Values may be integers or floating point numbers.
      bounds: [ -180.0, -90.0, 180.0, 90.0 ]

      # Tile extent in tile coordinate space
      extent: 4096

      # Buffer distance in tile coordinate space to optionally clip geometries
      buffer: 64

      # Boolean to control if geometries should be clipped or encoded as is
      clip_geom: true

      # Geometry type
      geometry_type: GEOMETRY

      # List of columns, that should be encoded as tile properties (required)
      properties:
        gid: int4

  # Associative arrays of function sources
  functions:
    function_source_id:
      # Schema name (required)
      schema: public

      # Function name (required)
      function: function_zxy_query

      # An integer specifying the minimum zoom level
      minzoom: 0

      # An integer specifying the maximum zoom level. MUST be >= minzoom
      maxzoom: 30

      # The maximum extent of available map tiles. Bounds MUST define an area
      # covered by all zoom levels. The bounds are represented in WGS:84
      # latitude and longitude values, in the order left, bottom, right, top.
      # Values may be integers or floating point numbers.
      bounds: [ -180.0, -90.0, 180.0, 90.0 ]
sprites:
  paths:
    # all SVG files in this dir will be published as a "my_images" sprite source
    # - ./icons   
  sources:
    # SVG images in this directory will be published as a "my_sprites" sprite source
    icons: ./icons      
mbtiles:
  paths:
    # scan this whole dir, matching all *.mbtiles files
    # - /dir-path
    # specific mbtiles file will be published as mbtiles2 source
    - ./world_cities.mbtiles
  sources:
    # named source matching source name to a single file
    # mb-src1: /path/to/mbtiles1.mbtiles       
# Font configuration
fonts:
  # A list of *.otf, *.ttf, and *.ttc font files and dirs to search recursively.
  - ./font/msyh.ttf

5. 启动服务

cmd命令窗口中输入命令.\martin.exe --config ./config.yaml启动。

6. 前端调用

前端调用服务的完整代码如下:

<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <link href="./public/lib/mapbox-gl.css" rel="stylesheet" />
  <style>
    html,
    body,
    #map {
      width: 100%;
      height: 100%;
      inset: 0;
      overflow: hidden;
      background-color: #efefef;
    }
  </style>
</head>

<body>
  <div id="map" class="map"></div>
  <script src="./public/lib/mapbox-gl.js"></script>
  <script>
    const url = 'http://localhost:3000/catalog'
    fetch(url).then(res => res.json()).then(res => {
      const { tiles, fonts } = res
      let sources = {}, fontsArray = Object.keys(fonts)
      Object.keys(tiles).forEach(tile => {
        sources[tile] = {
          type: "vector",
          tiles: [`http://127.0.0.1:3000/${tile}/{z}/{x}/{y}`],
        }
      })
      var style = {
        version: 8,
        name: "Mapbox Streets",
        sprite: "http://127.0.0.1:3000/sprite/icons",
        glyphs: `http://127.0.0.1:3000/font/${fontsArray.join(',')}/{fontstack}/{range}.pbf`,
        sources: sources,
        layers: [
          // 背景图层
          {
            id: 'background',
            type: 'background',
            paint: {
              'background-color': '#fff'
            }
          },
          // 省填充
          {
            id: "base_province_fill",
            type: "fill",
            source: "base_province",
            "source-layer": "base_province",
            paint: {
              "fill-color": "#f7f7f7",
              "fill-opacity": 0.8,
            },
          },
          // 建筑物填充
          {
            id: "theme_building",
            type: "fill",
            source: "theme_building",
            "source-layer": "theme_building",
            minzoom: 13,
            maxzoom: 14.4,
            paint: {
              "fill-color": "#eeeeee",
              "fill-opacity": 1,
            },
          },
          // 建筑物拉伸
          {
            id: "theme_building_extrusion",
            type: "fill-extrusion",
            source: "theme_building",
            "source-layer": "theme_building",
            minzoom: 13,
            paint: {
              "fill-extrusion-color": "#eeeeee",
              "fill-extrusion-opacity": 0.6,
              'fill-extrusion-height': 25
            },
          },
          // 建筑物描边
          {
            id: "theme_building_border",
            type: "line",
            source: "theme_building",
            "source-layer": "theme_building",
            minzoom: 13,
            maxzoom: 14.5,
            paint: {
              "line-color": "#eee",
              "line-opacity": 1,
            },
          },
          // 建筑物标注
          {
            "id": "theme_building_label",
            "type": "symbol",
            "source": "theme_building",
            'source-layer': 'theme_building',
            minzoom: 14.5,
            'layout': {
              'text-field': ['get', 'name'],
              'text-size': 12,
              'text-allow-overlap': false,
              'text-justify': 'center',
              "text-font": [
                "Microsoft YaHei"
              ]
            },
            paint: {
              'text-color': '#a3a3a3',
              'text-halo-color': '#fff',
              'text-halo-width': 1.2,
            }
          },
          // 省边界
          {
            id: "base_province",
            type: "line",
            source: "base_province",
            "source-layer": "base_province",
            paint: {
              "line-color": "#989ea7",
              "line-width": 0.5,
              'line-opacity': 1,
            },
          },
          // 城市边界
          {
            id: "base_city",
            type: "line",
            source: "base_city",
            "source-layer": "base_city",
            minzoom: 6,
            paint: {
              "line-color": "#b6ccd8",
              "line-width": 0.5,
              'line-opacity': 0.75,
            },
          },
          // 区县边界
          {
            id: "base_county",
            type: "line",
            source: "base_county",
            "source-layer": "base_county",
            minzoom: 8.2,
            paint: {
              "line-color": "#b6ccd8",
              "line-width": 0.3,
              'line-opacity': 0.8,
            },
          },
          // 一级水域面
          {
            id: "theme_hyd1_p",
            type: "fill",
            source: "theme_hyd1_p",
            "source-layer": "theme_hyd1_p",
            minzoom: 6,
            paint: {
              "fill-color": "#b2cefe",
              "fill-opacity": 1,
            },
          },
          // 二级水域面
          {
            id: "theme_hyd2_p",
            type: "fill",
            source: "theme_hyd2_p",
            "source-layer": "theme_hyd2_p",
            minzoom: 6,
            paint: {
              "fill-color": "#b2cefe",
              "fill-opacity": 1,
            },
          },
          // 一级水域线
          {
            id: "theme_hyd1_l",
            type: "line",
            source: "theme_hyd1_l",
            "source-layer": "theme_hyd1_l",
            paint: {
              "line-color": "#b2cefe",
              "line-width": 1,
            },
          },
          // 5级水域线
          {
            id: "theme_hyd5_l",
            type: "line",
            source: "theme_hyd5_l",
            "source-layer": "theme_hyd5_l",
            minzoom: 8.4,
            paint: {
              "line-color": "#b2cefe",
              "line-width": 0.8,
            },
          },
          // 路网
          {
            id: "theme_road",
            type: "line",
            source: "theme_road",
            "source-layer": "theme_road",
            minzoom: 6,
            paint: {
              "line-color": "#ffac4d",
              "line-width": 1,
            },
          },
          // 铁路
          {
            id: "theme_railway",
            type: "line",
            source: "theme_railway",
            "source-layer": "theme_railway",
            minzoom: 8.4,
            paint: {
              "line-color": "#bec4cd",
              "line-width": 2,
            },
          },
          // 铁路白色
          {
            id: "theme_railway_bg",
            type: "line",
            source: "theme_railway",
            "source-layer": "theme_railway",
            minzoom: 8.4,
            paint: {
              "line-color": "#fff",
              "line-width": 1.5,
            },
          },
          // 铁路间隔
          {
            id: "theme_railway_interval",
            type: "line",
            source: "theme_railway",
            "source-layer": "theme_railway",
            minzoom: 8.4,
            paint: {
              "line-color": "#bec4cd",
              "line-width": 1.5,
              "line-dasharray": [3, 3]
            },
          },
          // 国界线虚线
          {
            id: "base_boundry",
            type: "line",
            source: "base_boundry_l",
            "source-layer": "base_boundry_l",
            filter: ["==", "type", 1],
            paint: {
              "line-color": "#e04747",
              "line-width": 2,
              "line-dasharray": [3, 3]
            },
          },
          // 国界线
          {
            id: "base_boundry_l",
            type: "line",
            source: "base_boundry_l",
            "source-layer": "base_boundry_l",
            filter: ["!=", "type", 1],
            paint: {
              "line-color": "#e04747",
              "line-width": 2,
            },
          },
          // 九段线
          {
            id: "base_nineline",
            type: "line",
            source: "base_nineline",
            "source-layer": "base_nineline",
            paint: {
              "line-color": "#e04747",
              "line-width": 3,
            },
          },
          // 机场
          {
            "id": "theme_airport",
            "type": "symbol",
            "source": "theme_airport",
            'source-layer': 'theme_airport',
            minzoom: 8.2,
            'layout': {
              'icon-image': 'airport',
              'icon-size': 0.55,
              'icon-allow-overlap': true,
            },
            paint: {
              'icon-color': '#f00',
            }
          },
          // 区县名称
          {
            "id": "base_county_c",
            "type": "symbol",
            "source": "base_county_c",
            'source-layer': 'base_county_c',
            minzoom: 8.2,
            filter: ['!=', ['get', 'district'], '北京'],
            'layout': {
              'icon-image': 'capital',
              'icon-size': 0.32,
              'icon-allow-overlap': false,
              'text-field': ['get', 'district'],
              'text-size': 10,
              'text-allow-overlap': false,
              'text-justify': 'center',
              'text-offset': [0, 1.3],
              "text-font": [
                "Microsoft YaHei"
              ]
            },
            paint: {
              'text-color': 'rgb(80, 80, 80)',
              'text-halo-color': '#fff',
              'text-halo-width': 1.4,
            }
          },
          // 城市名称
          {
            "id": "base_city_c",
            "type": "symbol",
            "source": "base_city_c",
            'source-layer': 'base_city_c',
            minzoom: 6,
            filter: ['!=', ['get', 'district'], '北京'],
            'layout': {
              'icon-image': 'capital',
              'icon-size': 0.35,
              'icon-allow-overlap': false,
              'text-field': ['get', 'district'],
              'text-size': 11,
              'text-allow-overlap': false,
              'text-justify': 'center',
              'text-offset': [0, 1.3],
              "text-font": [
                "Microsoft YaHei"
              ]
            },
            paint: {
              'text-color': 'rgb(80, 80, 80)',
              'text-halo-color': '#fff',
              'text-halo-width': 1.8,
            }
          },
          // 省会城市
          {
            "id": "base_capital",
            "type": "symbol",
            "source": "base_capital",
            'source-layer': 'base_capital',
            filter: ['!=', ['get', 'name'], '北京'],
            maxzoom: 5.9,
            'layout': {
              'icon-image': 'capital',
              'icon-size': 0.38,
              'icon-allow-overlap': false,
              'text-field': ['get', 'name'],
              'text-size': 12,
              'text-allow-overlap': false,
              'text-justify': 'center',
              'text-offset': [0, 1.5],
              "text-font": [
                "Microsoft YaHei"
              ]
            },
            paint: {
              'text-color': 'rgb(80, 80, 80)',
              'text-halo-color': '#fff',
              'text-halo-width': 1.8,
            }
          },
          // 首都
          {
            "id": "base_capital_beijing",
            "type": "symbol",
            "source": "base_capital",
            'source-layer': 'base_capital',
            filter: ['==', ['get', 'name'], '北京'],
            'layout': {
              'icon-image': 'star',
              'icon-size': 0.5,
              'icon-allow-overlap': false,
              'text-field': ['get', 'name'],
              'text-size': 14,
              'text-allow-overlap': false,
              'text-justify': 'center',
              'text-offset': [0, 1.6],
              "text-font": [
                "Microsoft YaHei"
              ]
            },
            paint: {
              'text-color': 'rgb(255, 0, 0)',
              'text-halo-color': '#fff',
              'text-halo-width': 1.6,
              'icon-color': '#f00',
            }
          },
        ],
      };
      var map = new mapboxgl.Map({
        container: "map", // container ID
        style: style,
        center: [107.11040599933166, 34.26271532332011], // starting position [lng, lat]
        zoom: 3,
        minZoom: 3,
        doubleClickZoom: false,
        hash: false,
        localFontFamily: true,
        logoPosition: "bottom-right",
      });
      window.map = map
    })
  </script>
</body>

</html>

资源下载

相关资源上传到了CSDN,请异步到https://download.csdn.net/download/GISShiXiSheng/90417459下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303902.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全:防范NetBIOS漏洞的攻击

稍微懂点电脑知识的朋友都知道&#xff0c;NetBIOS 是计算机局域网领域流行的一种传输方式&#xff0c;但你是否还知道&#xff0c;对于连接互联网的机器来讲&#xff0c;NetBIOS是一大隐患。 漏洞描述 NetBIOS(Network Basic Input Output System&#xff0c;网络基本输入输…

一周学会Flask3 Python Web开发-客户端状态信息Cookie以及加密

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili HTTP是无状态&#xff08;stateless)协议。也就是说&#xff0c;在一次请求响应结束后&#xff0c;服务器不会留下任何关于对…

机器学习面试八股文——决战金三银四

大家好&#xff0c;这里是好评笔记&#xff0c;公主 号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记的任务是解读机器学习实践/面试过程中可能会用到的知识点&#xff0c;内容通俗易懂&#xff0c;入门、实习和校招轻松搞定。 公主号合集地址 点击进入优惠地…

【Akashic Records】THE EGG

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Akashic Records 文章目录 &#x1f4af;观后感一、宇宙的孤寂与个人成长&#xff1a;二、选择与责任&#xff1a;三、灵性与世界的连接&#xff1a;四、选择如何改变命运&#xff1a;结语&#xff1a; &#x1f4af;…

从零开始用react + tailwindcs + express + mongodb实现一个聊天程序(一)

项目包含5个模块 1.首页 (聊天主页) 2.注册 3.登录 4.个人资料 5.设置主题 一、配置开发环境 建立项目文件夹 mkdir chat-project cd chat-project mkdir server && mkdir webcd server npm init cd web npm create vitelatest 创建前端项目时我们选择javascrip…

ant design 疑惑记录 Dropdown.Button

onMenuClick是点击展开的 子项的点击事件 Actions的点击事件是什么&#xff1f; 解答&#xff1a; 也是个按钮Button&#xff0c;也有自己的onClick事件 const onMenuClick (e) > {console.log(click, e); }; const otherClick (e) > {console.log(其他操作主按钮…

SAP on Microsoft Azure Architecture and Administration (Ravi Kashyap)

SAP on Microsoft Azure Architecture and Administration (Ravi Kashyap)

Missing required prop: “maxlength“

背景&#xff1a; 封装一个使用功能相同使用频率较高的input公共组件作为子组件&#xff0c;大多数长度要求为200&#xff0c;且实时显示统计子数&#xff0c;部分input有输入提示。 代码实现如下&#xff1a; <template><el-input v-model"inputValue" t…

在windows下安装windows+Ubuntu16.04双系统(下)

这篇文章的内容主要来源于这篇文章&#xff0c;为正式安装windowsUbuntu16.04双系统部分。在正式安装前&#xff0c;若还没有进行前期准备工作&#xff08;1.分区2.制作启动u盘&#xff09;&#xff0c;见《在windows下安装windowsUbuntu16.04双系统(上)》 二、正式安装Ubuntu …

数据库驱动免费下载(Oracle、Mysql、达梦、Postgresql)

数据库驱动找起来好麻烦&#xff0c;我整理到了一起&#xff0c;需要的朋友免费下载&#xff1a;驱动下载 目前收录了Oracle、Mysql、达梦、Postgresql的数据库驱动的多个版本&#xff0c;后续可能会分享更多。

业务流程相关的权威认证和培训有哪些

业务流程的认证和培训种类繁多&#xff0c;旨在帮助专业人士掌握业务流程管理 (BPM) 的知识和技能&#xff0c;从而提升个人职业发展和组织运营效率。下面分别介绍&#xff1a; 一、 业务流程认证和培训的种类 业务流程的认证和培训可以大致分为以下几类&#xff0c;涵盖了不…

vivado修改下载器下载速率

Error Launching Program X Error while launching program: fpga configuration failed. DONE PIN is not HIGH 原因是下载器速度太快了。先从任务管理器中关闭hw_server.exe试一下,要是不行就按下面三种方法解决。 第一种方法可以不用修改下载速度,直接先从vivado中将bit流…

巧妙实现右键菜单功能,提升用户操作体验

在动态交互式图库中&#xff0c;右键菜单是一项能够显著提升用户操作便捷性的功能。它的设计既要响应用户点击位置&#xff0c;又需确保菜单功能与数据操作紧密结合&#xff0c;比如删除图片操作。以下将通过一段实际代码实现&#xff0c;展示从思路到实现的详细过程。 实现右键…

CASS11快捷键设置

快捷键增加如下&#xff1a; tr----trim bo---(-boundary) ro---rotate ed----explode of---offset qs---qselect dp---ptype re---regen rec---rectang br---break dis---distuser do---draworder

HTTP 常见状态码技术解析(应用层)

引言 HTTP 状态码是服务器对客户端请求的标准化响应标识&#xff0c;属于应用层协议的核心机制。其采用三位数字编码&#xff0c;首位数字定义状态类别&#xff0c;后两位细化具体场景。 状态码不仅是服务端行为的声明&#xff0c;更是客户端处理响应的关键依据。本文将从协议规…

如何使用3D高斯分布进行环境建模

使用3D高斯分布来实现建模&#xff0c;主要是通过高斯分布的概率特性来描述空间中每个点的几何位置和不确定性。具体来说&#xff0c;3D高斯分布被用来表示点云数据中的每一个点或体素&#xff08;voxel&#xff09;的空间分布和不确定性&#xff0c;而不是单纯地存储每个点的坐…

兰州百合基因组(36.68 Gb)-文献精读113

The evolutionary tale of lilies: Giant genomes derived from transposon insertions and polyploidization 百合的进化故事&#xff1a;由转座子插入和多倍化导致的巨型基因组 百合&#xff08;Lilium spp.&#xff09;&#xff0c;被誉为“球根花卉之王”&#xff0c;因其…

如何做实用、好用的矿用电子围栏(续篇)

1 写在前面 去年写了一篇文章《如何做实用、好用的矿用电子围栏》&#xff0c;初步探讨了一下矿用UWB的电子围栏的实现方法&#xff0c;阅读量超出预期&#xff0c;说明电子围栏需求度比较高&#xff0c;企业对安全生产越来越重视。当时写这篇文章时&#xff0c;由于时间和理解…

【ThreeJS Basics 1-5】动画 Animations

文章目录 Three JS 中的动画window.requestAnimationFrame(fn)基本代码修改显示器刷新率的对比基础的动画尝试不同帧率导致动画速率不同解决方案一&#xff1a;DeltaTime解决方案2&#xff1a;Clock方法3&#xff1a; 动画库 Gsap如何选择方案&#xff1f; Three JS 中的动画 …

WSL进阶使用指南

WSL2通过 Hyper-V 技术创建了一个轻量级的虚拟机&#xff08;VM&#xff09;&#xff0c;在这个虚拟机之上可以运行一个真正的 Linux 内核&#xff0c;这给希望同时使用 Windows 和 Linux 的开发人员提供了无缝高效的体验。本文会介绍一些使用WSL的知识&#xff0c;帮助你更好地…