基于MapboxGL的样式⽂件⾃动⽣成图例
MapboxGL是⼀个基于WebGL的地图绘制引擎,其采⽤⼀个json格式的⽂件进⾏描述,但是对于渲染的地图,Mapbox并没有提供图例的⽣成⽅法,因此需要⾃⼰根据这个样式描述⽂件来⽣成地图图例。
MapboxGL中数据与样式是分开的,地图的所有样式都是由这个唯⼀的样式描述⽂件来描述。并不是地图中的所有样式都需要图例,例如简单的⽂字注记就不需要⽣成图例,⽽且MapboxGL的样式中对同⼀个数据源(例如:铁路)会有多个样式图层(style layer)描述其样式(例如:灰⾊的实线图层加⽩⾊的虚线图层)。因此基于该样式⽂件绘制图例⾄少要先解决两个难题:
1. 从众多的样式中筛选出哪些样式需要绘制图例;
2. 从筛选出的样式中提取哪些样式描述的是同⼀个数据源。
⼀、筛选需要绘制图例的图层
⾸先我们需要将所有的样式图层进⾏分类,按照要素类型分为点、线、⾯三类,分别为pointLayers、lineLayers、polygonLayers。
其次分别从中筛选出需要绘制图例的图层,删掉不需要绘制图例的图层。筛选规则很简单,对于所有要素都需要满⾜以下条件:
1、当前地图的级别必须在样式图层的可见级别范围之内。例如当前地图为第8级,⽽某⼀个样式的可见范围是9-12,那么这个样式是可以被忽略的。
2、图层的visibility属性设置的为“visible”,即必须可见。
理论上来说只要满⾜以上两个条件,那么这个图层在当前地图级别就是可见的,但是对于点状要素来说还有⼀个条件:
3、如果为点状要素的样式,则该样式必须具有“icon-image”属性。即该点状符号具有图标,⽽不是纯⽂字。
⼆、合并同⼀数据源的图层
经过以上筛选后,上下的样式都是需要绘制图例的,但是有些样式可能描述的是同⼀个数据源,对于这些样式应该属于⼀个要素,因此需要合并。怎样判断哪些样式是属于统⼀数据源呢,基本原则如下:
1、type必须相同,都是线状或都是⾯状。
2、source属性必须相同,即同⼀数据源。
3、source-layer属性必须相同,即同⼀数据图层。
4、filter必须相同,具有相同的数据过滤条件。
满⾜以上要求被认为是描述的同⼀个数据要素。
三、绘制图例
经过以上步骤得到的应该就是所有需要绘制图例的样式了,⽽要对图例进⾏可视化就需要选择对应的渲染引擎对图例进⾏渲染,⽬前我使⽤过的有两种渲染⽅法:
1、采⽤WebGL渲染
考虑到MapboxGL本⾝就是基于WebGL渲染的,⽽现在筛选后的图例的样式正好与地图的样式具有相同的格式,可以考虑直接⽤MapboxGL渲染到地图上,这时就需要创建geojson数据源。根据点线⾯三种类型分别创建三种geojson的模板,然后根据筛选出的图例样式的类型,分别获取对应的geojson,并利⽤图例样式对其进⾏符号化。
2、采⽤svg渲染
采⽤WebGL的⽅法渲染缺点是不⽅便编辑,⽽且采⽤的经纬度的坐标,相当于重新建⽴⼀个map。⽽svg则更加轻量,并且可以缩放和编辑。
但是svg的样式描述采⽤的dom属性的⽅式,因此与不能直接使⽤筛选的图例样式,⽽要转换成svg⽀持的属性。
附件(图例⾃动⽣成实例):
① ⼀个完整的Style Json⽂件如下:
{
"name": "新闻",
"version": 8,
"sources": {
"data2012": {
"type": "vector",
"url":"192.9.105.205:8090/api/v1/tilesets/foxgis/admin"
}
},
"sprite": "192.9.105.205:8090/api/v1/sprites/foxgis/Hk6NFtw8/sprite",
"glyphs": "192.9.105.205:8090/api/v1/fonts/foxgis/{fontstack}/{range}.pbf",svg实例
"layers": [
{
"id": "背景",
"type": "background",
"paint": {
"background-color": "#87c2e4"
}
},
{
"id": "亚洲⾯",
"type": "fill",
"source": "data2012",
"source-layer": "asia_a",
"paint": {
"fill-color": "#ebecec",
"fill-opacity": 1,
"fill-outline-color": "#ebecec"
}
},
{
"id": "国界",
"type": "line",
"source": "data2012",
"source-layer": "china_l",
"maxzoom": 11,
"paint": {
"line-color": "#e8ae59",
"line-width": 5
}
},
{
"id":"国界光晕",
"type":"line",
"source":"data2012",
"source-layer":"china_l",
"minzoom":3,
"maxzoom": 11,
"paint":{
"line-offset":-3,
"line-color":"rgba(255, 214, 211, 0.98)", "line-width":{
"stops":[[3,4],[4,6],[6,8]]
}
}
},
{
"id": "省界线",
"type": "line",
"source": "data2012",
"source-layer": "boua_prov",
"minzoom": 4,
"maxzoom": 9,
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "rgb(150,150,150)",
"line-width": 1,
"line-dasharray": [1.5,3]
}
},
{
"id": "县界",
"source": "data2012",
"source-layer": "boua",
"metadata": {
"replaceLayer": true
},
"minzoom": 7,
"maxzoom": 11,
"type": "line",
"filter": ["==","pac",320111], "layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "rgb(0,0,255)", "line-width": 2,
"line-dasharray": [3,3]
}
},
{
"id":"铁路(实线)",
"source":"data2012",
"source-layer":"lrrl",
"minzoom":7,
"maxzoom":11,
"filter":["any",
["==","gb",410101],
["==","gb",410102],
["==","gb",410103],
["==","gb",410200]
],
"type":"line",
"paint":{
"line-width": 2.4,
"line-color":"#949494"
}
},
{
"id":"铁路(虚线)",
"source":"data2012",
"source-layer":"lrrl",
"minzoom":7,
"maxzoom":11,
"filter":["any",
["==","gb",410101],
["==","gb",410102],
["==","gb",410103],
["==","gb",410200]
],
"type":"line",
"paint":{
"line-width":1.2,
"line-color":"#fff",
"line-dasharray":[10,10]
}
},
{
"id": "省名注记",
"source": "data2012",
"source-layer": "prov_label", "type": "symbol",
"minzoom": 4,
"maxzoom": 5,
"layout": {
"text-size": 12,
"text-font": [
"STXinwei Regular"
],
"symbol-placement": "point",
"text-field": "{name}",
"text-max-width": 8
},
"paint": {
"text-color": "rgb(250,0,0)",
"text-halo-color": "rgb(255,255,255)", "text-halo-width": 1.5,
"text-halo-blur": 1
}
},
{
"id": "⾸都注记",
"type": "symbol",
"source": "data2012",
"source-layer": "agnp",
"filter": ["==","capname","北京"],
"minzoom": 3,
"maxzoom": 11,
"layout": {
"text-size": 14,
"icon-image": "star-15",
"text-font": ["SimHei Regular"],
"symbol-placement": "point",
"text-allow-overlap": false,
"text-offset": [0,1],
"text-anchor": "top",
"text-field": "{capname}",
"text-letter-spacing": 0.02,
"text-max-width": 8
},
"paint": {
"text-color": "rgb(255,0,0)",
"text-halo-color": "rgb(255,255,255)", "text-halo-width": 1.5,
"text-halo-blur": 1
}
},
{
"id": "省会城市注记",
"type": "symbol",
"source": "data2012",
"source-layer": "agnp",
"filter": ["==","class","AB"],
"minzoom": 5,
"maxzoom": 8,
"layout": {
"text-size": 15,
"icon-image": "circle-11",
"text-font": [
"SimHei Regular"
],
"symbol-placement": "point",
"text-offset": [0,0.7],
"text-anchor": "top",
"text-field": "{capname}",
"text-letter-spacing": 0.02,
"text-max-width": 8
},
"paint": {
"icon-color": "#ff0000",
"text-color": "rgb(20,20,20)",
"text-halo-color": "rgb(255,255,255)", "text-halo-width": 1.5,
"text-halo-blur": 1
}
},
{
"id": "地级市注记",
"type": "symbol",
"source": "data2012",
"source-layer": "agnp",
"minzoom": 7,
"maxzoom": 11,
"layout": {
"text-line-height": 1.2,
"text-size": 13,
"symbol-avoid-edges": true,
"icon-image": "circle-11",
"text-ignore-placement": false,
"text-max-angle": 38,
"text-font": [
"SimHei Regular"
],
"symbol-placement": "point",
"visibility": "visible",
"text-offset": [0,0.7],
"icon-optional": false,
"text-rotation-alignment": "viewport",
"text-anchor": "top",
"text-field": "{name}",
"text-letter-spacing": 0.02,
"text-max-width": 8
},
"paint": {
"icon-color": "#ff0000",
"text-color": "#fe001f",
"text-halo-color": "rgb(255,255,255)",
"text-halo-width": 1.5,
"text-halo-blur": 1
}
},
{
"id": "县注记",
"source": "data2012",
"source-layer": "agnp",
"filter": ["any",["==","class","AE"],["==","class","AF"]], "minzoom": 8,
"maxzoom": 11,
"type": "symbol",
"layout": {
"text-size": 13,
"icon-image": "circle-stroked-11",
"text-max-angle": 38,
"text-font": ["SimHei Regular"],
"symbol-placement": "point",
"text-anchor": "top",
"text-field": "{name}",
"text-letter-spacing": 0.02,
"text-max-width": 7
},
"paint": {
"text-color": "rgb(60,60,60)",
"text-halo-color": "rgb(255,255,255)",
"text-halo-width": 1.5,
"text-halo-blur": 1
}
}
]
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论