天天看點

mapboxgl 地圖樣式 - 唯一值渲染

mapboxgl 中提供了強大的地圖樣式編輯功能,樣式表達式是其一大特色。

唯一值渲染是GIS中常見的專題圖渲染方式,今天我們來看一下如何用 mapboxgl 中的樣式表達式實作這一效果。

在網上找了一份北京市的行政區劃圖,目标是各個區設定上不同的顔色。效果如下:

mapboxgl 地圖樣式 - 唯一值渲染

方式一:使用 case 表達式

這種做法的好處是可以靈活修改每個區的顔色。

"fill-color":[
    "case",
    ["boolean",["==",["get","name"],"懷柔區"],false],"#FFFFCC",
    ["boolean",["==",["get","name"],"密雲區"],false],"#CCFFFF",
    ["boolean",["==",["get","name"],"平谷區"],false],"#FFCCCC",
    ["boolean",["==",["get","name"],"通州區"],false],"#FFFF99",
    ["boolean",["==",["get","name"],"房山區"],false],"#CCCCFF",
    ["boolean",["==",["get","name"],"延慶區"],false],"#FFCC99",
    ["boolean",["==",["get","name"],"門頭溝區"],false],"#CCFF99",
    ["boolean",["==",["get","name"],"大興區"],false],"#66CCFF",
    ["boolean",["==",["get","name"],"順義區"],false],"#99CCFF",
    ["boolean",["==",["get","name"],"海澱區"],false],"#CCCCCC",
    ["boolean",["==",["get","name"],"西城區"],false],"#CCFFCC",
    ["boolean",["==",["get","name"],"東城區"],false],"#CC99CC",
    ["boolean",["==",["get","name"],"朝陽區"],false],"#99CC99",
    ["boolean",["==",["get","name"],"石景山區"],false],"#CCCC99",
    ["boolean",["==",["get","name"],"昌平區"],false],"#FF9969",
    ["boolean",["==",["get","name"],"豐台區"],false],"#999999",
    "black"
]
           

上面表達式的意思是,從資料中擷取 name 屬性的值,判斷是哪個區,然後設定相應的顔色。

case表達式文法,詳見官方說明

mapboxgl 表達式的基本文法:

1、一組中括号[ ]代表一個完整的表達式,中括号中第一個參數聲明表達式的類型,後面是表達式的參數。

2、表達式可以嵌套。

關于表達式的詳細介紹,後續會用單獨一篇文章來寫,這裡隻做個簡單說明。

上面這段表達式如果翻譯成 js 大緻是這樣的:

function getColor(feature){	//feature是geojosn格式中的Feature
    if(feature.properties.name === "懷柔區"){		
        return "#FFFFCC"
	}
	else if(features[i].name === "密雲區"){	
        return "#CCFFFF"
	}
    ...
    else{
        return "black"
    }
}
           

線上示例,浏覽器 F12 可以檢視完整代碼。

方式二:使用 match 表達式

match 和 case 類似,但在寫法上更為簡潔

"fill-color":[
    "match",
    ["get","name"],
    "懷柔區","#FFFFCC",
    "密雲區","#CCFFFF",
    "平谷區","#FFCCCC",
    "通州區","#FFFF99",
    "房山區","#CCCCFF",
    "延慶區","#FFCC99",
    "門頭溝區","#CCFF99",
    "大興區","#66CCFF",
    "順義區","#99CCFF",
    "海澱區","#CCCCCC",
    "西城區","#CCFFCC",
    "東城區","#CC99CC",
    "朝陽區","#99CC99",
    "石景山區","#CCCC99",
    "昌平區","#FF9969",
    "豐台區","#999999",
    "black"
]
           

翻譯成js是下面這樣:

function getColor(feature){	//feature是geojosn格式的Feature
    switch(feature.properties.name){		//["get","name"]
        case "懷柔區":
        	return "#FFFFCC"
        case "密雲區":
        	return "#CCFFFF"
        ...
        default
        	return "black"
    }
}
           

線上示例

方式三:根據 id 比對顔色

前兩種表達式适合資料量較小時使用。當資料量較大時,可以通過設定一組顔色,根據資料中的某個id字段進行比對來實作。

"fill-color":[
    "to-color",[
        "at",
        ["%", ["get", "adcode"], 13],
        ["literal",["#00FFCC","#CCFFFF","#FFCCCC","#FFFF99","#CCCCFF","#FFCC99","#CCFF99","#66CCFF","#99CCFF","#CCFFCC","#99CC99","#CCCC99","#FF9969"]]
    ]
]
           

上面表達式的意思是,會用資料中 adcode 的屬性值除以13然後取餘數,根據餘數從顔色數組中取一個顔色。

表達式詳細說明:

  1. ["get", "adcode"]

    表達式

    get

    從資料中擷取

    adcode

    屬性的值。
  2. ["%", ["get", "adcode"], 13]

    表達式

    %

    adcode

    的值除以13并取餘數,這裡的13代表顔色數組的個數。
  3. ["literal",["#00FFCC",...]]

    表達式

    literal

    用來聲明一個顔色數組,因為在這裡中括号被預設是表達式,是以想要定義真正的數組就要用

    literal

    包裝一下。
  4. ["at",["%", ["get", "adcode"], 13],["literal","#00FFCC",...]]

    表達式

    at

    是根據求餘的值從顔色數組中取顔色。
  5. ["to-color", ["at",["%", ["get", "adcode"], 13],["literal","#00FFCC",...]]]

    表達式

    to-color

    是将字元串轉為mapboxgl 的顔色類型,不然會報錯。

翻譯成js是下面這樣:

function getColor(feature){	//feature是geojosn格式的Feature
    const colors = ["#00FFCC","#CCFFFF","#FFCCCC","#FFFF99","#CCCCFF","#FFCC99","#CCFF99","#66CCFF","#99CCFF","#CCFFCC","#99CC99","#CCCC99","#FF9969"]
    const index = feature.properties.adcode % 13
    return colors[index]
}
           

線上示例

方式四:從屬性中取顔色

這種方式比較簡單,就是直接把顔色放到資料中,通過 get 表達式擷取出來直接用。缺點就是要去改資料。

下圖是在資料中增加顔色資料:

mapboxgl 地圖樣式 - 唯一值渲染

使用表達式直接擷取顔色:

"fill-color":["get","color"]
           

線上示例

方式五:分圖層設定顔色

通過圖層的

filter

篩選條件實作,每個區設定成一個圖層,然後設定每個圖層的顔色。

圖層樣式設定方式:

[
    {
        "id": "beijing-haidian",
        "type": "fill",
        "source": "beijing",
        "paint":{
            "fill-color":"#FFCC99"
        },
        "filter":["==",["get","name"], "海澱區"]
	},
    {
        "id": "beijing-chaoyang",
        "type": "fill",
        "source": "beijing",
        "paint":{
            "fill-color":"#FFCCCC"
        },
        "filter":["==",["get","name"], "朝陽區"]
    }
    ...
]
           

這種做法的好處是,可以在 maputnik 中直接選顔色,因為在 maputnik 中,表達式是不支援直接在界面上選顔色的,隻能自己編輯。

選顔色效果如下圖:

mapboxgl 地圖樣式 - 唯一值渲染

這種方式的缺點也很明顯:圖層由一個變成了16個,style 檔案會變的很啰嗦,圖層管理不太友善。

線上示例

最後

後續會将表達式作為一個系列更新幾篇,敬請關注。

原文位址:http://gisarmory.xyz/blog/index.html?blog=mapboxglStyleUniqueValue

歡迎關注《GIS兵器庫》

本文章采用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定 進行許可。歡迎轉載、使用、重新釋出,但務必保留文章署名《GIS兵器庫》(包含連結:  http://gisarmory.xyz/blog/),不得用于商業目的,基于本文修改後的作品務必以相同的許可釋出。