Sử dụng GeoJSON trong Leaflet

GeoJSON đang trở thành một định dạng dữ liệu rất phổ biến trong số nhiều công nghệ và dịch vụ GIS, nó vô cùng đơn giản, gọn nhẹ, dễ đọc và Leaflet xử lý GeoJSON cũng khá tốt. Trong ví dụ này, bạn sẽ biết được cách tạo ra và tương tác với một bản đồ vector được tạo ra từ các GeoJSON objects.

About GeoJSON

Theo According to http://geojson.org:

GeoJSON is a format for encoding a variety of geographic data structures. A GeoJSON object may represent a geometry, a feature, or a collection of features. GeoJSON supports the following geometry types: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection. Features in GeoJSON contain a geometry object and additional properties, and a feature collection represents a list of features.

GeoJSON là một định dạng để mã hóa một loạt các cấu trúc dữ liệu địa lý. Một object GeoJSON có thể đại diện cho một hình (hình học), tính năng hoặc tập hợp nhiều tính năng. GeoJSON hỗ trợ các kiểu hình học sau: Điểm (Point), Đường liên tục (LineString), Đa giác(Polygon), Đa điểm (MultiPoint), Nhiều đường liên tục (MultiLineString), nhiều đa giác (MultiPolygon) và tập hình học (GeometryCollection).

Leaflet hỗ trợ tất cả các loại GeoJSON nói trên nhưng FeaturesFeatureCollections hoạt động tốt nhất vì chúng cho phép bạn mô tả các tính năng với một tập hợp các thuộc tính. Thậm chí chúng ta có thể sử dụng những thuộc tính này để tạo ra các vectơ Leaflet riêng. Dưới đây là ví dụ về tính năng GeoJSON đơn giản:

var geojsonFeature = {
    "type": "Feature",
    "properties": {
        "name": "Coors Field",
        "amenity": "Baseball Stadium",
        "popupContent": "This is where the Rockies play!"
    },
    "geometry": {
        "type": "Point",
        "coordinates": [-104.99404, 39.75621]
    }
};

The GeoJSON layer

Các GeoJSON object được thêm vào bản đồ thông qua một GeoJSON layer (lớp GeoJSON). Để tạo nó và thêm nó vào bản đồ, chúng ta có thể sử dụng đoạn code như sau:

L.geoJSON(geojsonFeature).addTo(map);

Các object GeoJSON cũng có thể được truyền như một mảng các đối tượng GeoJSON hợp lệ.

var myLines = [{
    "type": "LineString",
    "coordinates": [[-100, 40], [-105, 45], [-110, 55]]
}, {
    "type": "LineString",
    "coordinates": [[-105, 40], [-110, 45], [-115, 55]]
}];

Ngoài ra, chúng ta có thể tạo một lớp GeoJSON trống và gán nó cho một biến để chúng ta có thể thêm nhiều tính năng vào nó sau này.

var myLayer = L.geoJSON().addTo(map);
myLayer.addData(geojsonFeature);

Options

style

Style option có thể được sử dụng để style các features theo hai cách khác nhau. Trước tiên, chúng ta có thể truyền một đối tượng đơn giản mà định dạng tất cả các đường dẫn (các đường nối liền và các đa giác) theo cùng một cách:

var myLines = [{
    "type": "LineString",
    "coordinates": [[-100, 40], [-105, 45], [-110, 55]]
}, {
    "type": "LineString",
    "coordinates": [[-105, 40], [-110, 45], [-115, 55]]
}];

var myStyle = {
    "color": "#ff7800",
    "weight": 5,
    "opacity": 0.65
};

L.geoJSON(myLines, {
    style: myStyle
}).addTo(map);

Ngoài ra, chúng ta có thể truyền một hàm style các feature riêng dựa trên các thuộc tính của chúng (feature). Trong ví dụ dưới đây, chúng ta kiểm tra thuộc tính "party" và style các hình đa giác một cách hợp lý:

var states = [{
    "type": "Feature",
    "properties": {"party": "Republican"},
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-104.05, 48.99],
            [-97.22,  48.98],
            [-96.58,  45.94],
            [-104.03, 45.94],
            [-104.05, 48.99]
        ]]
    }
}, {
    "type": "Feature",
    "properties": {"party": "Democrat"},
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-109.05, 41.00],
            [-102.06, 40.99],
            [-102.03, 36.99],
            [-109.04, 36.99],
            [-109.05, 41.00]
        ]]
    }
}];

L.geoJSON(states, {
    style: function(feature) {
        switch (feature.properties.party) {
            case 'Republican': return {color: "#ff0000"};
            case 'Democrat':   return {color: "#0000ff"};
        }
    }
}).addTo(map);

pointToLayer

Các điểm được xử lý khác với các polylines và polygons. Theo mặc định các điểm đánh dấu đơn giản được vẽ từ GeoJSON Points. Chúng ta có thể thay đổi điều này bằng cách truyền một hàm pointToLayer trong một đối tượng GeoJSON options khi tạo lớp GeoJSON. Hàm này được truyền vào một LatLng và được trả về một thực thể của ILayer, trong trường hợp này có thể là một Marker hoặc CircleMarker.

Ở đây chúng ta đang sử dụng pointToLayer option để tạo một CircleMarker:

var geojsonMarkerOptions = {
    radius: 8,
    fillColor: "#ff7800",
    color: "#000",
    weight: 1,
    opacity: 1,
    fillOpacity: 0.8
};

L.geoJSON(someGeojsonFeature, {
    pointToLayer: function (feature, latlng) {
        return L.circleMarker(latlng, geojsonMarkerOptions);
    }
}).addTo(map);

Chúng ta cũng có thể thiết lập thuộc tính style trong ví dụ này - Leaflet đủ thông minh để áp dụng các style cho các GeoJSON points nếu bạn tạo một lớp vector như hình tròn bên trong hàm pointToLayer.

onEachFeature

Tùy chọn filter có thể được sử dụng để kiểm soát khả năng hiển thị của các GeoJSON features. Để thực hiện điều này chúng ta truyền một hàm như một filter option. Hàm này được gọi cho mỗi feature trong lớp GeoJSON của bạn và được truyền vào freaturelayer. Sau đó bạn có thể sử dụng các giá trị trong thuộc tính của feature để kiểm soát sự hiển thị bằng cách trả về true hoặc false.

Trong ví dụ bên dưới "Busch Field" sẽ không hiển thị trên bản đồ.

var someFeatures = [{
    "type": "Feature",
    "properties": {
        "name": "Coors Field",
        "show_on_map": true
    },
    "geometry": {
        "type": "Point",
        "coordinates": [-104.99404, 39.75621]
    }
}, {
    "type": "Feature",
    "properties": {
        "name": "Busch Field",
        "show_on_map": false
    },
    "geometry": {
        "type": "Point",
        "coordinates": [-104.98404, 39.74621]
    }
}];

L.geoJSON(someFeatures, {
    filter: function(feature, layer) {
        return feature.properties.show_on_map;
    }
}).addTo(map);

Nhớ xem trang ví dụ để xem chi tiết những gì có thể làm với lớp GeoJSON.