配置离线地图的方法

前半部分文章参考:Mapbox本地离线部署 - 简书

一 离线部署说明

从官网抄一个HelloWorld的例子,完整代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiYW56aGlodW4iLCJhIjoiY2lsdnhjdjN5MDFvMHVia3NpYTlnbmUzaSJ9.twlExCjpR7uwH2IiFC7aDA';
var map = new mapboxgl.Map({
    container: 'map', // container id
    style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location
    center: [-74.50, 40], // starting position [lng, lat]
    zoom: 9 // starting zoom
});
</script>
</body>
</html>

从该例子看,平常的js库只需要将js,css存放本地就可以离线使用了,但是mapbox比较特殊:

  • 声明了一个accessToken,通过这个accessToken 才能访问mapbox在线的地图,样式等。
  • mapbox的map构造,直接一个style,定制了整个地图的样式。本地离线部署,必须要知道这个style的定义才行。

查询官网Style Specification资料,style除了这个url声明之外,还可以通过以下方式定义:

{
    "version": 8,
    "name": "Mapbox Streets",
    "sprite": "mapbox://sprites/mapbox/streets-v8",
    "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
    "sources": {...},
    "layers": [...]
}

参数说明如下:

  • version:样式版本,当前必须必须设置8。
  • name:样式名称,设置一个可读的名称描述即可。
  • sprite:mapbox地图使用的图标。
  • glyphs:mapbox地图使用的标注字体。
  • sources: mapbox地图使用的地图服务资源定义。
  • layers: mapbox地图使用的图层定义。

明显的,当我们尝试将mapbox离线本地化时,应当解决如下内容:

  • mapbox-gl.js,mapbox-gl.css存储本地服务器
  • layers,sources 图层本地化
  • sprite 图标本地化
  • glyphs 字体本地化

二 图层本地化

先保持HelloWorld的所有内容不变,尝试自定义一个xyz的osm底图,替换原底图即可。

 "sources": {
     "osm-tiles": {
         "type": "raster",
         "tiles": [
                 "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
          ],
          "tileSize": 256
       }
  },
  "layers":[{
      "id": "123",
       "type": "raster",
       "source": "osm-tiles",
       "source-layer": "osmtiles"
  }]

sources参数说明:

  • sources是地图资源对象,以key,value组成,sources里的key不能重复,唯一声明一个地图资源的组成。
  • value里的type是资源的类型,必须是 vector, raster, raster-dem, geojson, image, video中的一种。当前声明是xyz的png图片组成的底图,所以声明类型是raster。
  • value里的tiles是xyz底图的url模板组合,tileSize声明一个切片宽高,一般切片都是是256*256的,所以此处声明256 。

layers参数说明:

  • layers是个数组,数组每一项代表一个图层。
  • id是每个图层的主键,每个图层的id必须不能重复。
  • type,声明一个图层的类型。
  • source,图层的地图数据来源,指向sources里的某个key的资源定义,比如sources里定义了一个osm-tiles的资源,该图层数据来源指向这个资源,即将key的值输入此处。
  • source-layer:图层的名称,可以当做是图层别名,用以描述图层的。

完整的代码和效果如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiYW56aGlodW4iLCJhIjoiY2lsdnhjdjN5MDFvMHVia3NpYTlnbmUzaSJ9.twlExCjpR7uwH2IiFC7aDA';
var map = new mapboxgl.Map({
    container: 'map', // container id
    style:{
        "version": 8,
        "name": "Mapbox Streets",
        "sprite": "mapbox://sprites/mapbox/streets-v8",
        "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
         "sources": {
             "osm-tiles": {
                 "type": "raster",
                 "tiles": [
                   "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
                  ],
                 "tileSize": 256
             }
        },
      "layers":[{
          "id": "123",
           "type": "raster",
           "source": "osm-tiles",
           "source-layer": "osmtiles"
      }]
    },
    center: [-74.50, 40], // starting position [lng, lat]
    zoom: 9 // starting zoom
});
</script>
</body>
</html>

 

图层本地化效果

实际使用时,使用mapbox加载wms,wmts,xyz这种栅格或者矢量切片等地图图层等。加载自己的地图服务这个初级目标达成。

三 图标本地化

3.1 图标离线使用

mapbox明显是偏向于互联网应用的地图库,它使用sprite这种将所有图标放一起的方式,减少小图片资源请求次数,在高并发的应用情况下,起到优化应用的目的,比如高德,百度地图都是使用sprite形式组合的地图图标,我们先尊重这样的设计。
上个例子中,图标定义形式是:"sprite": "mapbox://sprites/mapbox/streets-v8",初次接触一脸懵逼,不知道这个是啥意思,简单点,我们f12打开networ查看如图:

sprites请求
浏览器根据我们的定义,实际发送了两个url请求,一个png图片,一个json位置描述信息。暂时将这两个文件存储本地服务器:

sprites本地存储


然后仅仅将之前的代码,仅仅更改url为本地服务器的url即可:

 "sprite": "http://localhost:8080/mapbox_build/sprite/sprite",

这样,sprite图标的问题就解决了。

3.2 图标生成工具

mapbox提供了一个spritezero工具,用于自定义生成mapbox的sprite。spritezero工具用于将一个文件夹的svg矢量图片,转换成一个sprite的png图片和一个json文件。
本文简单介绍下,方便以后创建自己地图的sprite。
环境约束
操作系统:centos 7.2,win下基本装不上。
node:node6.3.0,其他高版本亲测很多难以装上。

3.2.1 安装node6.3.0

[root@localhost ~]# cd /usr/local
[root@localhost local]# wget http://nodejs.org/dist/v6.3.0/node-v6.3.0.tar.gz
[root@localhost local]# tar -zxvf node-v6.3.0.tar.gz
[root@localhost local]# vi /etc/profile
#编辑内容如下:
export NODE_HOME=/usr/local/node-v6.3.0
export PATH=$NODE_HOME/bin:$PATH
#保存退出

#启用profile生效
[root@localhost local]# source /etc/profile

#查看node,npm版本
[root@localhost local]# node -v
v6.3.0
[root@localhost local]# npm -v
3.10.3

#linux下root执行权限,重要,一定要操作
[root@localhost local]# chown -R root.root ./node-v6.3.0

3.2.2 安装spritezero,spritezero-cli

npm install -g @mapbox/spritezero
npm install -g @mapbox/spritezero-cli --unsafe-perm

3.2.3 sprite创建

icons输入资源

将icons下的svg图标转成sprite:

[root@localhost test]# spritezero sprite ./icons

输出结果

神奇的生成了一个叫sprite.png和sprite.json文件。

四 字体本地化

mapbox中使用的字体,也是pbf格式而不是tff格式,需要使用工具转换,查询资料发现,genfontgl这个node库可以执行将tff文件转成mapbox可用的pbf字体。

4.1 全局安装genfontgl

[root@localhost local]# npm i genfontgl -g

4.2 字体转换

用法:genfontgl OpenSans-Regular.ttf [output location]
示例:将OpenSans-Regular.ttf转换成pbf存到当前目录。

[root@localhost test]# genfontgl OpenSans-Regular.ttf ./
Process OpenSans-Regular.ttf

4.3 字体应用

本地字体

将转换完成的字体,存放到本地服务器,修改glyphs参数即可:

 "glyphs": "http://localhost:8080/mapbox_build/fonts/{fontstack}/{range}.pbf",

疑问:fontstack,range这个参数占位是干嘛的?实际上,fontstack和range会被具体的字体类型和这个字在字体中所处的实际范围给替换了,我们先用一个矢量图层的样式来说明:

map.on('load', function () {
    map.addLayer({
        "id": "points",
        "type": "symbol",
        "source": {
            "type": "geojson",
            "data": {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-77.03238901390978, 38.913188059745586]
                    },
                    "properties": {
                        "title": "Mapbox DC",
                        "icon": "monument"
                    }
                }, 
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-122.414, 37.776]
                    },
                    "properties": {
                        "title": "Mapbox SF",
                        "icon": "harbor"
                    }
                }]
            }
        },
        "layout": {
            "icon-image": "{icon}-15",--矢量数据中properties的icon注入
            "text-field": "{title}",--矢量数据的properties中tile注入
            "text-font": ["Open Sans Regular"],  --字体,fontstack占位符就是对应这个声明。
            "text-offset": [0, 0.6],
            "text-anchor": "top"
        }
    });
});

mapbox大量使用注入的形式,比如文字标注绑定了矢量数据的title字段,图标绑定了icon字段,字体用我们转换后的本地字体。
完整代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Display a map</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiYW56aGlodW4iLCJhIjoiY2lsdnhjdjN5MDFvMHVia3NpYTlnbmUzaSJ9.twlExCjpR7uwH2IiFC7aDA';
var map = new mapboxgl.Map({
    container: 'map', // container id
    style:{
        "version": 8,
        "name": "Mapbox Streets",
        "sprite": "http://localhost:8080/mapbox_build/sprite/sprite",
        "glyphs": "http://localhost:8080/mapbox_build/fonts/{fontstack}/{range}.pbf",
         "sources": {
             "osm-tiles": {
                 "type": "raster",
                 "tiles": [
                   "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
                  ],
                 "tileSize": 256
             }
        },
      "layers":[{
          "id": "123",
           "type": "raster",
           "source": "osm-tiles",
           "source-layer": "osmtiles"
      }]
    },
    center: [-74.50, 40], // starting position [lng, lat]
    zoom: 9 // starting zoom
});




map.on('load', function () {
    map.addLayer({
        "id": "points",
        "type": "symbol",
        "source": {
            "type": "geojson",
            "data": {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-77.03238901390978, 38.913188059745586]
                    },
                    "properties": {
                        "title": "Mapbox DC",
                        "icon": "monument"
                    }
                }, 
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-122.414, 37.776]
                    },
                    "properties": {
                        "title": "Mapbox SF",
                        "icon": "harbor"
                    }
                }]
            }
        },
        "layout": {
            "icon-image": "{icon}-15",
            "text-field": "{title}",
            "text-font": ["Open Sans Regular"],
            "text-offset": [0, 0.6],
            "text-anchor": "top"
        }
    });
});
</script>
</body>
</html>

4.4 可能遇到的问题标注与图标

4.4.1 npm install EACCES: permission denied

原因是npm的存储目录没有操作权限,解决方法:

[root@localhost local]# chown -R root.root /usr/local/node-v6.3.0

4.4.2 genfontgl命令,ibstdc++.so.6: version `GLIBCXX_3.4.20' not found

版本问题,具体操作参考《关于libstdc++.so.6: version `GLIBCXX_3.4.20' not found问题解决》

五 最终部署

我们已经逐渐将字体,图标,图层,资源都采用本地的服务,但上面例子还是公网的mapbox-gl和accessToken,其实当资源都是使用本地的,accessToken 就没用了,我们只用把js,css也放到本地就可以了,完整代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>hello world</title>
    <meta charset="utf-8" />
    <script src='./plugin/mapbox-gl.js'></script>
    <link href='./plugin/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>
     <div id='map'></div>
     <script>
        //mapboxgl.accessToken = 'pk.eyJ1IjoiZnJlZWdpcyIsImEiOiJjam04dXRudWwwNXczM3Fqb3dkd201dGZzIn0.jvDsB3YWibUpk1oR9vva1A';
        var map = new mapboxgl.Map({
            container: 'map',
            style: {
                 "version": 8,
                 "name": "Mapbox Streets",
                 "sprite": "http://localhost:8080/mapbox_build/sprite/sprite",
                 "glyphs": "http://localhost:8080/mapbox_build/fonts/{fontstack}/{range}.pbf",
                 "sources": {
                    "osm-tiles": {
                        "type": "raster",
                        'tiles': [
                            "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
                        ],
                        'tileSize': 256
                    }
                  },
                  "layers":[{
                         "id": "123",
                         "type": "raster",
                         "source": "osm-tiles",
                         "source-layer": "osmtiles"
                  }]
            },
            center: [-96, 37.8],
            zoom: 3
        });




map.on('load', function () {
    map.addLayer({
        "id": "points",
        "type": "symbol",
        "source": {
            "type": "geojson",
            "data": {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-77.03238901390978, 38.913188059745586]
                    },
                    "properties": {
                        "title": "Mapbox DC",
                        "icon": "monument"
                    }
                }, 
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-122.414, 37.776]
                    },
                    "properties": {
                        "title": "Mapbox SF",
                        "icon": "harbor"
                    }
                }]
            }
        },
        "layout": {
            "icon-image": "{icon}-15",
            "text-field": "{title}",
            "text-font": ["Open Sans Regular"],
            "text-offset": [0, 0.6],
            "text-anchor": "top"
        }
    });
});
     </script>
</body>
</html>

所有的资源都是本地了,可以做离线应用了。本地使用的话,mapbox的很多在线服务我们是使用不了了的,都要自己离线开发定制自己的服务。

实现: 

Mapbox配置离线地图:

cesium配置离线地图:

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-baidu-map是一个在Vue框架中使用百度地图的插件。它允许我们在Vue应用中使用百度地图的相关功能和服务。而离线地图配置则是vue-baidu-map插件中的一个特性,它允许我们加载并使用离线地图离线地图配置主要包括以下几个步骤: 1. 下载离线地图包:在使用离线地图之前,我们需要将需要的地图区域的离线地图包下载到本地。百度提供了离线地图下载工具,我们可以通过该工具选择需要的地图区域并进行下载。下载完成后,会生成一个.db文件,这个文件包含了离线地图的数据。 2. 配置vue-baidu-map插件:在Vue项目中使用vue-baidu-map插件,并配置相关参数。我们需要在项目中安装vue-baidu-map插件,并在使用地图的组件中引入并配置相关参数,包括引入插件、设置ak秘钥、设置离线地图路径等。 3. 加载离线地图:在组件中加载离线地图。通过在地图组件中的代码中指定离线地图的路径,将离线地图加载到地图组件中。加载完成后,离线地图将会显示在地图上,并且支持常用的地图操作,如缩放、拖拽等。 4. 使用离线地图:在加载完成离线地图后,我们可以像使用在线地图一样使用离线地图。可以设置中心点、标记点、绘制覆盖物等。同时,离线地图还支持地图的交互操作和事件。 总的来说,使用vue-baidu-map的离线地图配置,我们可以在Vue应用中加载和使用离线地图。通过下载离线地图包,并在插件中进行相应的配置和加载操作,我们可以在Vue项目中使用离线地图,并获得和在线地图类似的功能和体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值