進階mapbox GL之paint和filter

  • 2020 年 3 月 31 日
  • 筆記

概述

通過前面的文章初識mapbox GL我們對mapbox GL有了一個相對比較全面的認識,本節結合一些示例,重點講述一下mapbox GL裏面的filter和paint的用法。

說明

本文中的示例數據源是北京的區邊界數據,格式為geojson,數據字段與詳情如下:

filter

filter是layer裏面的一個屬性,通過一些條件表達式實現僅顯示與過濾器匹配的要素,即圖層的過濾顯示,其官方說明如下圖:

1、==和!=

==!=可實現根據某個字段圖層的過濾展示。如:只在地圖上展示昌平區或者在地圖上展示除昌平外的所有區域。

// 只在地圖上展示昌平區  var filter = ['==', 'name', '昌平區'];    //地圖上展示除昌平外的所有區域  var filter = ['!=', 'name', '昌平區'];

2、>、>=、<、<=

>、>=、<、<=是通過比較大小的方式,實現圖層的過濾,所以此處需要的字段得是數字類型或者通過to-number將字段轉換成數字類型。如:展示count>=10的區域。

var filter = ['>=', 'count', 10];

3、in和match

inmatch都可實現對圖層根據某個字段進行多值過濾。如:在地圖上展示昌平區和海淀區。

// in  var filter = [    'in',    'name',    '昌平區',    '海淀區'  ];  // match  var filter = [    "match",    [      "get",      "name"    ],    [      "昌平區",      "海淀區",    ],    true,    false  ]

接着上面的例子,如果我們要實現在地圖中展示除海淀和昌平區外的其他區域,我們可以直接用!in和將match的條件互換的方式來實現,如下:

// in  var filter = [    '!in',    'name',    '昌平區',    '海淀區'  ];  // match  var filter = [    "match",    [      "get",      "name"    ],    [      "昌平區",      "海淀區",    ],    false,    true  ]

4、多條件

有時候,會存在多條件的過濾,例如:我們選擇type==1並且count>10的區域,我們可以這麼寫:

var filter = [    'all',    ['>=', 'count', 10],    ['==', 'type', 1]  ]

當然,有時我們會存在根據幾何類型來進行過濾,此時,我們可用:

var filter = [      "==",      ["geometry-type"],      "LineString"    ];

paint

paint是layer的一個屬性,負責圖層的渲染與呈現。

1、match

match通常用於枚舉型的字段渲染,如唯一值渲染。

'circle-color': [   'match',   ['get', 'type'],   1, '#FFD273',   2, '#E86D68',   '#A880FF'  ]

2、case

case通常用於分段數值型的字段渲染,值域是前關後開,如分級渲染。

'circle-color': [    'case',    ['<', ['get', 'speed'], 10.8], 'rgba(0,0,0,0)', //<10.8    ['<', ['get', 'speed'], 17.2], 'rgba(153, 255, 153, .9)', //>=10.8 & <17.2    ['<', ['get', 'speed'], 24.5], 'rgba(102, 204, 255, .9)',    ['<', ['get', 'speed'], 32.7], 'rgba(255, 255, 102, .9)',    ['<=', ['get', 'speed'], 41.5], 'rgba(253, 139, 0, .9)',    ['<=', ['get', 'speed'], 50.1], 'rgba(255, 51, 0, .9)', //>=41.5 & <50.1    'rgba(255, 0, 255, .9)' // 默認值, >=50.1  ]

注意

  1. 第一個的判斷是<;
  2. 中間的判斷是>=<;
  3. 最後一個判斷是>=;

3、step

step和上面的case很類似,只是值域是前開後關的。

// <=100, 100-500, >500  "circle-color": [    "step",    ["get", "count"],    "#51bbd6", 100,    "#f1f075", 500,    "#f28cb1" // other  ]    'circle-color': [    'step',    ['to-number', ['get', 'CID']],    '#0098A3',  10,    '#00CA8D', 20,    '#37C508', 30,    '#98F300',  40,    '#EFFF85'  ]

說明:

  1. 對於非數值型的字段,我們可以用to-number對字段進行轉換。

4、interpolate

interpolate,中文的翻譯是「插值」,在mapbox GL中,我們可通過interpolate實現按照比例的插值渲染。

// <=8, 8-10, >10  "background-color": [    "interpolate",    ["linear"],    ["zoom"],    8, "rgba(0, 0, 255, 0.2)",    10, "rgba(255, 0, 0, 0.2)"  ]    // <=20, 20-60, 60-100, >100  'fill-extrusion-color': [    'interpolate',    ['linear'],    ['get', 'height'],    20, 'rgba(255,255,191, 0.65)',    60, 'rgba(253,174,97, 0.65)',    100, "rgba(215,25,28, 0.65)"  ]    // exponential,指數  "fill-opacity": [    "interpolate",    ["exponential", 1.5],    ["zoom"],    2, 0.3,    7, 0  ]

說明:

  1. zoom是一個特殊字符,特製地圖的縮放級別,同樣的還有geometry-type,特指的是geom類型。

完整測試代碼如下:

var rootPath = 'http://127.0.0.1:3000/mapbox/lib/';  // var filter = ['match', ['get', 'name'],  //   ['昌平區', '海淀區'], false, true  // ];  // var filter = ['!in', 'name', '昌平區', '海淀區'];    // var filter = [  //   'all',  //   ['>=', 'count', 10],  //   ['==', 'type', 1]  // ];    var filter = ['>=', 'count', 0];  // var fillColor = 'rgba(255, 0, 0, 0.5)';    // 唯一值圖  // var fillColor = [  //   'match',  //   ['get', 'type'],  //   1, '#FFD273',  //   2, '#E86D68',  //   '#A880FF'  // ];    // 分級色彩圖  // var fillColor = [  //   'case',  //   ['<', ['get', 'count'], 10], '#FFD273',  //   ['<', ['get', 'count'], 20], '#E86D68',  //   ['<', ['get', 'count'], 30], '#A880FF',  //   ['<', ['get', 'count'], 40], '#68E0E8',  //   ['<=', ['get', 'count'], 50], '#9BFF69',  //   '#000' // 默認值  // ];    // 比例符號圖  var fillColor = [    'interpolate',    ['linear'],    ['get', 'count'],    15, '#FFD273',    30, '#E86D68',    50, '#9BFF69'  ];    // 步長圖  // var fillColor = [  //   'step',  //   ['get', 'count'],  //   '#0098A3',  //   10, '#00CA8D',  //   20, '#37C508',  //   30, '#98F300',  //   40, '#EFFF85'  // ]  var mapStyle = {    "version": 8,    "name": "Dark",    "sources": {      "geojson": {        type: 'geojson',        data: '../data/beijing.geojson'      }    },    "glyphs": rootPath + "fonts/mapbox/{fontstack}/{range}.pbf",    "layers": [{        "id": "background",        "type": "background",        "paint": {          "background-color": "#999"        }      },      {        'id': 'geojson',        'source': 'geojson',        'type': 'fill',        'paint': {          'fill-color': fillColor,          'fill-opacity': .8        },        filter: filter      },      {        'id': 'geojson-border',        'source': 'geojson',        'type': 'line',        'paint': {          'line-color': '#FFF',          'line-width': 1.5        },        filter: filter      },      {        'id': 'points',        'type': 'symbol',        'source': 'geojson',        'layout': {          'text-field': ['get', 'name'],          "text-size": 22        },        paint: {          'text-color': '#000000'        },        filter: filter      }    ]  };  map = new mapboxgl.Map({    container: 'map',    maxZoom: 18,    minZoom: 6,    zoom: 8,    center: {      lng: 116.6552,      lat: 40.2482    },    style: mapStyle,    attributionControl: false,    localIdeographFontFamily: "'全新硬筆行書簡'"  });