SuperMap iClient 9D for MapboxGL地图风格浅析

来源:互联网 发布:live2d有mac版本的吗 编辑:程序博客网 时间:2024/06/07 12:36

作者:dominating

前言

随着SuperMap iServer 9D的发布,iServer增加了许多的新功能,其中之一就是地图服务模块,矢量切片(tileFeature)资源增加了支持 mvt的表述。mvt矢量切片格式是mapbox标准的矢量切片,而我们的SuperMap iClient 9D 加入了MapboxGL框架,所以我们就可以通过SuperMap iClient 9D来对接SuperMap iServer 9D发布的矢量切片服务,制作出精美的矢量地图。

今天就简单为大家介绍下如何使用SuperMap iClient 9D for MapboxGL来修改地图风格。

定义MapboxGL的map对象

var map = new mapboxgl.Map({        container: 'map', // container id        style: {            "version": 8,            "sources": {                "vector-tiles": {                    "attribution": attribution,                    "type": "vector",                    "tiles": [host + "/iserver/services/map-beijing/rest/maps/beijingMap/tileFeature.mvt?returnAttributes=true&compressTolerance=-1&width=512&height=512&viewBounds={bbox-epsg-3857}&expands=0:0_2,132_128,138_64,141_32,143_16,145_8,147_4"]                },            },            "sprite": "http://iclient.supermapol.com/web/styles/osm/sprite",            "glyphs": host + "/iserver/services/map-beijing/rest/maps/beijingMap/tileFeature/sdffonts/{fontstack}/{range}.pbf",            "layers": []        },        center: [116.4, 39.9],        minZoom: 10,        zoom: 11    });

tiles,矢量切片的服务地址
sprite,用于渲染背景图案,填充图片,线条图案,点图标的图片url地址(由两个文件组成,索引文件和图片文件,可以使用iClient官网的资源,具体可以参考mapboxGL官方说明)

sprite.json sprite.png

glyphs,字体库,字体样式资源url地址。 如果任意图层使用了text-field布局属性,此属性不能为空。(下面的symbol图层文字样式将会用到)
layers,需要绘制的图层,将按照顺序进行绘制

"layers": [  {            "id": " 四级道路L@北京",  //唯一的图层名称            "type": "line",   //图层类型            "source": "vector-tiles",            "source-layer": "四级道路L@北京",            "layout": {   //布局样式                "line-cap": "round",                "line-join": "round",                "visibility": "visible"            },            "paint": {  //绘制样式                "line-color": "hsl(224, 22%, 45%)",                "line-width": {                    "base": 1.55,                    "stops": [                        [13,1.8],                        [20,20]                    ]                },                "line-opacity": 0.9            }        }]

咱们主要围绕layers来介绍。layers属性列出了可用的所有图层,图层的类型由type属性指定,并且必须是background, fill, line, symbol, raster, circle, fill-extrusion中的一种。
除了背景类型的图层,每个图层都需要引用source。 图层将从source中获取数据,可选地过滤要素,然后定义这些要素的样式。
图层拥有两个子属性,用于确定如何渲染该图层的数据:layout和paint属性。
本篇文章主要介绍我们常用的几种图层类型

图层类型

background 背景图层

顾名思义也就是作为地图背景的图层,不需要指定source

map.addLayer({            "id": "background",            "type": "background",            "layout": {                "visibility":"visible"            },            "paint": {                "background-color": "hsl(55, 1%, 20%)"  //背景颜色            }        });

黑色背景蓝色背景

可以设置不同颜色的背景图层。注意,MapboxGL中颜色以各种允许的格式写成JSON字符串,HTML格式的十六进制,rgb,rgba,hsl和hsla,也可以使用预定义的HTML颜色名称,如”blue”,”yellow

{  "line-color": "#ff0",  "line-color": "#ffff00",  "line-color": "rgb(255, 255, 0)",  "line-color": "rgba(255, 255, 0, 1)",  "line-color": "hsl(100, 50%, 50%)",  "line-color": "hsla(100, 50%, 50%, 1)",  "line-color": "yellow"}

fill 填充图层

可以理解为面图层

        map.addLayer({  //绿地            "id": "绿地R@北京",            "type": "fill",            "source": "vector-tiles",            "source-layer": "绿地R@北京",            "paint": {                "fill-color": "hsl(100, 58%, 76%)",  //填充色                "fill-opacity": {  //填充透明度                    "base": 1,                    "stops": [  //线性变化                        [                            5,                            0                        ],                        [                            7,                            0.5                        ]                    ]                }            },        });        //湖泊、水库        map.addLayer({            "id": "湖泊、水库R@北京",            "type": "fill",            "source": "vector-tiles",            "source-layer": "湖泊、水库R@北京",            "paint": {                "fill-color": "hsl(196, 80%, 70%)"            }        });

这里写图片描述

可以对面的填充色,透明度,轮廓线颜色进行修改
fill-outline-color ,填充的轮廓颜色。默认为填充颜色

stop属性

可以注意到代码中我们使用到了一个“stop”属性,这个值被指定为一个函数,该函数是根据输入和输出值进行定义,一组输入值和输出值被称为”stop”。该函数允许你通过使用缩放地图级别来改变地图要素的外观。

"fill-color": "hsl(100, 58%, 76%)",                  "fill-opacity": {                      "base": 1,                    "stops": [                          [5,0],                        [7,0.5]                    ]                }

每个stop是由两个元素组成的数组,第一个是缩放级,第二个是函数输出值。以上例子中,当缩放级为5时,fill-opacity为0,当缩放级为7时,fill-opacity为0.5。fill-opacity的值将从第5级的0线性过渡到第七7级的0.5。”base”参数为内插曲线指数基数,将会影响到两个stop之间的线性变化。我们可以通过两张图来增加理解

base为1 base为0.5

当前我的缩放级为5.2,可以看出不同base值的曲线的值是不一样的。

line 线图层

map.addLayer({            "id": " 三级道路L@北京",            "type": "line",            "source": "vector-tiles",            "source-layer": "三级道路L@北京",            "paint": {                "line-width": {   //线宽                    "base": 1.5,                    "stops": [                        [11,1],                        [18,10]                    ]                },                "line-color": "hsl(0, 0%, 100%)",  //线颜色            }        });        map.addLayer({            "id": " 二级道路L@北京",            "type": "line",            "source": "vector-tiles",            "source-layer": "二级道路L@北京",            "paint": {                "line-width": 4,                "line-color": "hsl(230, 24%, 87%)",            }        });        map.addLayer({            "id": "一级道路L@北京1",            "type": "line",            "source": "vector-tiles",            "source-layer": "一级道路L@北京",            "layout":{                "line-cap":"butt",    //线段末端样式                "line-join":"miter"   //线段交汇处样式            },            "paint": {                "line-width": {                    "base": 1.5,                    "stops": [                        [11,6],                        [18,26]                    ]                },                "line-color": "hsl(230, 24%, 87%)",                "line-opacity": {   //线透明度                    "base": 1,                    "stops": [                        [10.99,0],                        [11,1]                    ]                },            }        });

这里写图片描述

以上例子的line图层,有三种不同样式的道路。我们可以对线的颜色,宽度,透明度,光晕效果进行修改,以及对线头,线交汇处等这样的细节作出调整
其他常用的线样式属性:
line-blur:线的模糊度,默认为0
line-gap-width:在一条线实际路径外画一条线壳。值表示内部间隙的宽度。

symbol 符号图层

包括文字,图标。

        //道路名称        map.addLayer({            "id": " 一级道路Name",            "type": "symbol",   //类型为symbol            "source": "vector-tiles",            "source-layer": "一级道路L@北京",            "layout": {                "text-line-height": 1.1,   //行高                "text-size": {      //字体大小                    "base": 1.5,                    "stops": [                        [13.99,12],                        [20,24                    ]                },                "text-font": [    //字体类型                    "DIN Offc Pro Italic",                    "Arial Unicode MS Regular"                ],                "symbol-placement": "line",   //符号位置,默认为point,由于是道路名称所以设置为line                "text-field": "{道路名称}",    //需要显示的字段名称                "text-letter-spacing": 0.1,   //字间距                "text-max-width": 5    //文本换行最大行宽            },            "paint": {                "text-color": "hsl(0, 0%, 0%)",   //字体颜色                "text-halo-color": "hsl(0, 0%, 100%)",  //字体光晕颜色                "text-halo-width": 1.25,  //光晕宽度                "text-opacity": {  //文字透明度                    "base": 1,                    "stops": [                        [13.99,0],                        [14,1]                    ]                },            },        });        map.addLayer({            "id": "医疗卫生@北京",            "type": "symbol",            "source": "vector-tiles",            "source-layer": "医疗卫生@北京",            "layout": {                "icon-image": "hospital-11",  //图标id                "text-offset": [0, -0.5],  //文字偏移量                "text-anchor": "bottom",  //文字锚点,支持center, left, right, top, bottom, top-left, top-right, bottom-left, bottom-right,默认center                "text-field": "{NAME}",                "text-size": 12            },            "paint": {                "text-color": "hsl(0, 0%, 78%)",                "text-halo-color": "#212121",                "text-halo-width": 1,                "text-halo-blur": 0            }        });        map.addLayer({            "id": "其它@北京2",            "type": "symbol",            "source": "vector-tiles",            "source-layer": "其它@北京",            "layout": {                "icon-image": "car-11",                "text-offset": [0, -0.5],                "text-anchor": "bottom",                "text-field": "{NAME}",                "text-size": 12            },            "filter": [   //过滤条件                "==",                "NAME",                "停车场"            ],            "paint": {                "text-color": "hsl(0, 0%, 0%)",                "text-opacity": 1,                "text-halo-color": "hsl(0, 0%, 100%)",                "text-halo-width": 1,                "text-halo-blur": 1            }        });

这里写图片描述

以上例子可以看出来,我们可以通过symbol图层对点,线的标签以及点符号进行绘制。我们几乎可以对它们进行任意的操作。以下是我们在symbol图层中需要注意的地方:
layout中的symbol-placement,默认为point,如果要显示线标注,需要修改为line,这样就沿线标注了
text-field的值为需要显示的字段名称,用{fieldname}格式填写
text-anchor ,文字的锚点,包括有center, left, right, top, bottom, top-left, top-right, bottom-left, bottom-right,默认center
text-offset,文字偏移量,正值表示右和下,负值表示左和上
icon-image,用于绘制的图片在sprite中的图像名称,所以配文字图层的时候,我们需要知道sprite中有哪些图片和对应的名称

filter过滤器

可以看出我们最后添加的图层上使用了过滤器filter,MapboxGL的过滤器可以说是非常强大的。过滤器支持以下形式的数组:
存在过滤(Existential Filters)

["has", key] feature[key] exists["!has", key] feature[key] does not exist

比较过滤器(Comparison Filters)

["==", key, value] equality: feature[key] = value["!=", key, value] inequality: feature[key] ≠ value[">", key, value] greater than: feature[key] > value[">=", key, value] greater than or equal: feature[key] ≥ value["<", key, value] less than: feature[key] < value["<=", key, value] less than or equal: feature[key] ≤ value

设置成员资格过滤器(Set Membership Filters)

["in", key, v0, ..., vn] set inclusion: feature[key] ∈ {v0, ..., vn}["!in", key, v0, ..., vn] set exclusion: feature[key] ∉ {v0, ..., vn}

组合过滤(Combining Filters)

["all", f0, ..., fn] logical AND: f0 ∧ ... ∧ fn["any", f0, ..., fn] logical OR: f0 ∨ ... ∨ fn["none", f0, ..., fn] logical NOR: ¬f0 ∧ ... ∧ ¬fn

key必须是一个字符串,用来标识要素属性或者是下面的特殊键:

  • “$type”:要素类型,该key可以和”==”, “!=”, “in”,与”!in”一起使用。值可能为”Point”, “LineString”, 和”Polygon”
  • “$id”:要素标识符,该key可以与”==”, “!=”, “has”, “!has”, “in”, 和”!in” 一起使用

value必须是一个字符,数字或者布尔值才能用来比较属性值,如

["==", "NAME", "停车场"]

设置成员资格过滤器可以用来测试字段是否匹配多个值。这个过滤就是要求要素的class必须是”street_major”, “street_minor”, “street_limited”中的一个。

["in", "class", "street_major", "street_minor", "street_limited"]

“all”,”any”,和”none”操作符用于创建复合过滤。值f0,…,fn必须是过滤表达式,比如以下的例子

[  "all",  ["==", "class", "street_limited"],  [">=", "admin_level", 3],  ["!in", "$type", "Polygon"]]

这个组合过滤器由三个过滤表达式组成,要求此要素必须满足这三个条件,class需要是”street_limited”,admin_level必须大于等于3,类型type不能是多边形。当然你也可以换成any,满足其中之一或者多个条件,或者使用none来取反。

结语

以上的话就是MapboxGL地图风格中常用的几种图层类型以及相关函数的简单介绍。可以看出如果要配出一幅精美的地图的话是非常需要耐心和时间的。其实我们也可以借助Mapbox的mapbox studio可视化编辑工具来制作地图。我们可以在工具中将地图的风格配置好,然后导出风格文件,做相关修改后使用在我们自己的地图中。

这里写图片描述

Mapbox studio地址:https://www.mapbox.com/mapbox-studio/

更多详细请参考:https://www.mapbox.com/mapbox-gl-js/style-spec