MapBox矢量切片及本地调用流程
- tippecanoe工具切片(目标文件.mbtiles)
- tippecanoe安装
- OSX系统执行命令
$ brew install tippecanoe
关于Homebrew介绍和使用查看链接Homebrew介绍和使用 - 简书
- Ubuntu系统依次执行下列命令
$ yum install sqlite-devel.x86_64 -y
$ yum install -y gcc automake autoconf libtool make
$ yum install -y gcc gcc-c++
$ yum install zlib-devel
$ Y
$ mkdir /data
$ cd /data
$ git clone GitHub - mapbox/tippecanoe: Build vector tilesets from large collections of GeoJSON features.(下载数据路径)
$ git clone tippecanoe: Build vector tilesets from large collections of GeoJSON features.(下载数据路径)
$ rm -rf tippecanoe(路径下载数据失败,删除目录)
$ git clone https://gitee.com/ssjylsg/tippecanoe.git(下载数据路径)
$ cd tippecanoe
$ make -j
$ make install
-
- Tippecanoe常用参数说明
简写 | 全称 | 说明 |
-o file.mbtiles | --output=file.mbtiles | 输出文件名称 |
-e directory | --output-to-directory=directory | 输出文件至指定路径 |
-f | --force | 如果存在同名文件,执行过程中会自动替换 |
-F | --allow-existing | 如果存在同名文件,则保留原文件 |
-s projection | --projection=projection | 指定投影坐标系,目前支持EPSG:4326,EPSG:3857两种,默认前者 |
-z zoom | --maximum-zoom=zoom | 指定生成切片的最高缩放级别,默认到14级 |
-zg | --maximum-zoom=g | 根据空间要素估算一个合适的缩放级别 |
-Z zoom | --minimum-zoom=zoom | 指定生成切片的最低缩放级别,默认到0级 |
-ae | --extend-zooms-if-still-dropping | 从指定级别到最大缩放级别,删除或简化要素 |
-R zoom/x/y | --one-tile=zoom/x/y | 指定最小、最大缩放级别 |
-d detail | --full-detail=detail | 最大缩放级别的分辨率,默认12,即切片分辨率为 2^12=4096 |
-D detail | --low-detail=detail | 最小缩放级别的分辨率,默认12,即切片分辨率为 2^12=4096 |
-m detail | --minimum-detail=detail | 如果切片分辨率过大,将尝试最小分辨率 |
-x name | --exclude=name | 从所有要素中排出某个或某几个属性 |
-y name | --include=name | 从所有要素中提取某个或某几个属性,没有指定的属性将被排除 |
-X | --exclude-all | 排除要素所有属性,仅对几何图形进行切片 |
-M bytes | --maximum-tile-bytes=bytes | 指定切片最大字节数,默认500k |
-O features | --maximum-tile-features=features | 指定切片要素个数,默认200000 |
-pf | --no-feature-limit | 不要将切片限制为200,000个要素 |
-pk | --no-tile-size-limit | 不要将切片限制为500k字节 |
-pC | --no-tile-compression | 不要压缩PBF矢量切片数据 |
-pg | --no-tile-stats | 不要在tileset元数据中统计行,不统计会增加上传时间 |
--tile-stats-attributes-limit=count | 指定切片最多包含的统计信息,默认1000 | |
--tile-stats-sample-values-limit=count | 根据指定值计算切片属性统计信息,默认1000 | |
--tile-stats-values-limit=count | 统计tilestats中唯一属性值,默认100 | |
-as | --drop-densest-as-needed | 如果切片太大,尝试通过增加要素之间的最小间距将其减小到500K以下。 该间距适用于整个缩放级别 |
-ad | --drop-fraction-as-needed | 从每个缩放级别动态删除一些要素,以使切片保持在500K大小限制之下。适用于整个缩放级别 |
-an | --drop-smallest-as-needed | 从每个缩放级别动态删除最小的要素(即最短的线或最小的多边形),以使切片保持在500K大小限制之下。 此选项不适用于点要素。 |
-aN | --coalesce-smallest-as-needed | 将每个缩放级别的最小要素(即最短的线或最小的多边形)动态合并到其他附近的要素中,以使大的区块保持在500K大小限制之下。主要用于多边形,以保持多边形覆盖的完整原始区域,同时仍以某种方式减少特征数量。 小多边形的属性不会保留到组合要素中(通过--accumulate属性除外),只保留其几何形状。 此外,嵌套多边形合并的多边形可能不一定是直接封闭的要素。 |
-aD | --coalesce-densest-as-needed | 动态地将每个缩放级别的最密集要素合并到其他附近的要素中,以使切片保持在500K大小限制之下。 (主要适用于多边形。) |
-aS | --coalesce-fraction-as-needed | 动态地将每个缩放级别的一小部分要素合并到其他附近要素中,以使切片保持在500K大小限制之下。(主要适用于多边形。) |
-pd | --force-feature-limit | 从切片动态删除一部分要素,使其低于500K大小限制。可能使切片边界看起来很难看。 (类似于-ad但是单独应用于每个切片,而不是整个缩放级别。) |
-aC | --cluster-densest-as-needed | 尝试通过增加要素之间的最小间距来减小其大小,并从每个组中留下一个占位符要素(参考) |
其他参数请阅读https://github.com/mapbox/tippecanoe
-
- 切片(以geoJson为例)
(1)数据准备
利用QGIS将shape数据转化为geoJson,注意数据编码为GBK,否则会出现中文乱码,影像后期配图,同时数据坐标为WGS84,或Web墨卡托投影数据。
(2)执行切片命令
以运城项目数据为例:
tippecanoe -o yuncheng.mbtiles -M 3000000 -z 19 -s EPSG:3857 BLDNUMPT.geojson BLDPL.geojson CITYPL.geojson COUNTYLN.geojson COUNTYPL.geojson COUNTYPT.geojson FUNCPL.geojson HYDPL.geojson poi.geojson RAILWAYLN.geojson REPREST.geojson ROAD.geojson TOWNLN.geojson TOWNPL.geojson TOWNPT.geojson VEGPL.geojson
tippecanoe -o LA.mbtiles -M 20000000 -Z 0 -z 18 -s EPSG:4326 -pC BLDPG.geojson POI.geojson ROAD.geojson AHCityT.geojson AHCityM.geojson CD.geojson FUNCPG.geojson FUNCPT.geojson HYGPG.geojson HYGPT.geojson LACityT.geojson FUNCPGxx LouHao.geojson VEGPG.geojson VEGPT.geojson QuXianD.geojson QuXianM.geojson ShengM.geojson LACityM.geojson RAILWAY.geojson XiangZhenD.geojson FUNCPTxx.geojson
tippecanoe -o LA.mbtiles -M 20000000 -Z 17 -z 18 -s EPSG:4326 -pC BLDPG.geojson
-o:最终输出文件名yuncheng.mbtiles
-M:指定切片最大字节数3000000byte(因为切片过程中,每个层级报>500k,到第7级报错,tippecanoe could not make tile 7/103/50 small enough,加上此参数解决)
-z:切片最大缩放层级19,不指定只切14级
-s:指定数据投影EPSG:3857(数据是web墨卡托投影,不指定汇报未指定投影错误,但程序不停止,默认EPSG:4326)
-pC:不要压缩PBF矢量切片数据,因为第一次没有添加该参数,导出切片后发现前端不能直接调用,需要解压转换数据格式,浪费很多时间,在切片过程中,添加该参数后,可能需要重新修改-M后的数值。
注意:利用Mapbox Studio配图时,需要上传.mbtiles文件,为确保数据安全,重新切一版样例数据或偏移数据,以运城项目为例,利用上述命令切偏移数据后,将结果文件上传至Mapbox Studio平台时,因为切片数据量过大上传失败,所以在切偏移数据时,没有添加-M参数,为避免(tippecanoe could not make tile 7/103/50 small enough)错误,添加-ad命令,切图后上传成功。
tippecanoe -o yuncheng.mbtiles -z 19 -s EPSG:3857 -ad BLDNUMPT.geojson BLDPL.geojson CITYPL.geojson COUNTYLN.geojson COUNTYPL.geojson COUNTYPT.geojson FUNCPL.geojson HYDPL.geojson poi.geojson RAILWAYLN.geojson REPREST.geojson ROAD.geojson TOWNLN.geojson TOWNPL.geojson TOWNPT.geojson VEGPL.geojson
- mbutil工具导出pbf(目标文件.pbf)
- mbutil安装
- 克隆mbutil项目
git clone git://github.com/mapbox/mbutil.git
cd mbutil
# get usage
./mb-util -h
- 全局安装mb-util
sudo python setup.py install
# then you can run:
mb-util
-
- Mbutil参数说明
简写 | 全称 | 说明 |
-h | --help | 显示此帮助消息并退出 |
--scheme=SCHEME | 切片的平铺方案。默认为“xyz”(z / x / y),其他选项是“tms”,也是z / x / y, 但使用翻转的y坐标和复制的“wms” MapServer WMS TileCache目录结构“z / 000/000 / x / 000/000 / y.png”,和“zyx”这是格式vips dzsave --layout谷歌使用。 | |
--image_format=FORMAT | 切片格式,png, jpg, webp or pbf | |
--grid_callback=CALLBACK | 用于控制UTFGrid切片的JSONP回调的选项。 如果网格不能用作JSONP,可以删除,指定--grid_callback =“”的回调 | |
--do_compression | 做压缩 | |
--silent | 指示操作是否以后台方式运行 |
注意:需要Python环境2.6以上版本
Git网址:https://github.com/mapbox/mbutil
-
- 导出pbf
只需将准确数据.mbtiles文件进行导出,执行以下命令
mb-util --image_format=pbf yuncheng.mbtiles tiles
压缩文件命令
zip -r 17.zip 17
-
- 解压缩pbf
如果tippecanoe切片过程中没有添加-pC参数, 通过mbutil直接导出的pbf文件不能直接在前端使用,需要在经过gzip等操作处理才能使用。具体操作方式如下:
cd tiles
// 执行gzip压缩
gzip -d -r -S .pbf *
// 重命名(非必要,如果不执行这一步那么前端访问使用的是 xxx/{z}/{x}/{y},否则就就是 xxx/{z}/{x}/{y}.pbf)
find . -type f -exec mv '{}' '{}'.pbf \;
- MapBox Studio配图及注意事项
- 上传.mbtiles文件
- 打开Mapbox | Maps, Navigation, Search, and Data网站,注册账号并登录
- 依次点击Start Building、Start by desining a map开始配图
- 配图流程
- 点击Add layer弹出Source资源框,点击Upload,即可上传自己的.mbtiles资源,上传完成后,可以在目录结构中生成自己的source目录
- 如上图,点击yuncheng,即可看到图层文件
- 依次点击每个图层加载至页面,注意每次点击后选择type类型,点线面分别选择Circle、Line、Fill,如果要配成三维立体图形,选择Fill extrusion,标注选择Symbol
- 其他按键如下图所示
-
- 特别要素配图
- 关于道路
以铁路为例,黑白格相间,需要上传两条道路进行复合配图,黑线宽度稍宽在底层,白线稍窄在上层,同时,通过dash参数将其设置成虚线。(其他道路复合样式也需要多次上传重复图层)
- 关于标注
每个需要标注的图层都需要重复上传一个Symbol类型的相同图层,标注符号(icon)可以上传自己的svg数据,配图过程中需要注意注记与符号相对位置关系,避免压盖,另外,道路需要沿道路走向标注,在Placement中选择如下图所示选项
- 关于立体建筑
需要立体显示的建筑,在加载图层的时候类型选择Fill extrusion,配图过程中,以某字段数值作为拉伸高度,同时,用相同数据层的Fill类型至于Fill extrusion底部以显示建筑阴影。(其他符合样式都需要注意图层顺序)
-
- 发布地图
- 发布地图
所有图层配图完成后,点击网页右上角Publish按钮进行地图发布
- 样式下载
完成发布后,点击右上角Share按钮,弹出下图提示框,点击Mapbox Basic Template即可下载样式文件,包括标注样式中的符号图标。
关于不同图层的层级显示利用Style across zoom range等参数进行设置
- MapBox矢量切片调用及本地化部署
- 本地化sprite
通过HTTP请求可以发现,sprite的配置,会导致两个请求,一个sprite.png的请求,一个是sprite.json的请求。sprite.png请求的结果如下:
通过上图,基本可以看出来这是图标的集合,通过把所有的图标放在一起,减少了HTTP请求次数,从而起到优化作用。Mapbox肯定很精通这种方式。既然是集合图片,获取其中的某一个图片,自然就需要坐标位置,图片大小等信息,为此不难猜测sprite.json里面存储的是什么信息了。在浏览器端获取在线png及json代码。
由于图片比较多,暂且放置一部分内容在上面。通过上面的内容可以看出,基本和我们猜想的一样。既然Mapbox GL JS采用这种方式加载图标,那么我们准守这种约定,在本地提供图标合集和信息,基本上也能解决问题。所以我们大胆的尝试一下修改sprite为本地路径: "sprite": "./", 修改之后测试一下,发现请求的地址确实变成本地的了:http://127.0.0.1:3209/.json, http://127.0.0.1:3209/.png。我们还需要取一个名字,比如这样设置,"sprite": "./sprite"。在本地准备好sprite.png和sprite.json这两个文件就好了。
主要参考https://www.jianshu.com/p/693f38ec5730
-
- 字体本地化(glyphs)
- 下载源码node-fontnik-release
wget https://github.com/mapbox/node-fontnik/archive/v0.5.0.tar.gz
- 安装
#解压缩
tar -xzf v0.5.0.tar.gz
cd node-fontnik-0.5.0
#安装库文件
#这个必须执行到,未执行需要卸载重装,需要curl
apt-get install curl
#一定要使用全局代理运行
#一定要使用全局代理运行
#一定要使用全局代理运行
./install_mason.sh
#安装node相关
npm install
#编译
make
- 使用
- 准备需要转换字体的ttf文件,这里使用微软雅黑 msyh.ttf
- 编写需要转换使用的js convert.js
var fontnik = require('.');var fs = require('fs');var path = require('path');
var convert = function(fileName, outputDir) {
var font = fs.readFileSync(path.resolve(__dirname + "/" + fileName));
output2pbf(font, 0, 255, outputDir);}
function output2pbf(font, start, end, outputDir) {
if (start > 65535) {
console.log("done!");
return;
}
fontnik.range({font: font, start: start, end: end}, function(err, res) {
var outputFilePath = path.resolve(
__dirname + "/" + outputDir + "/" + start + "-" + end + ".pbf");
fs.writeFile(outputFilePath, res, function(err){
if(err) {
console.error(err);
} else {
output2pbf(font, end+1, end+1+255, outputDir);
}
});
});}
convert("./msyh.ttf", "./msyh");
- 编写需要转换使用的js convert.js
- 将msyh.ttf 和convert.js 复制到node-fontnik-0.5.0路径下(按最后一行代码,建立msyh文件夹)
- 运行js转换文字,出现 done! 则为转换成功。
- 转换结果为XX-YY.pbf的字体文件夹
- 前端调用
- 目录结构
- 总目录
style.json与icons文件夹是MapBox Studio配图后下载的样式文件
- lib目录
- sprite目录
- glyphs目录
注意:mapbox 默认请求Open Sans Regular,Arial Unicode MS Regular两种字体,实际上本次配图只用到了Open Sans Regular字体,为了规避前端字体报错,此次将文件夹命名为“Open Sans Regular,Arial Unicode MS Regular”,另:参考https://blog.youkuaiyun.com/qq_17451827/article/details/76348875中内容,是要在代码中指定请求字体,但是需要在每个标注图层的Layout对象中添加下图代码,此处用“text-font”:[“Open Sans Regular”]尝试成功。
- html(注意样式JSON文件引用)
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>mbview - vector</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src="lib/mapbox-gl.js"></script>
<link rel="stylesheet" href="lib/mapbox-gl.css">
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
var map = new mapboxgl.Map({
container: 'map',
style: 'http://localhost:5500/style.json',
});
var latlonExtend = '110.203,34.595,112.045,35.767'
var tem = latlonExtend.split(',');
var extend = [[tem[0], tem[1]], [tem[2], tem[3]]]
map.fitBounds(extend);
</script>
</body>
</html>
- 改JSON引用代码(注意tiles、sprite、glyphs引用)