簡體   English   中英

使用實時數據對GeoJSON文件中的許多標記進行樣式化

[英]Styling a lot of markers from GeoJSON File with Live Data

我有一個動態創建的GeoJSON文件,其中包含具有特定緯度/經度,時間戳和類型信息的數據。 此數據會不斷更新,需要實時顯示在Google地圖上。 這是一個片段:

{ "type": "FeatureCollection","features": [
{"type": "Feature",
    "geometry": {
        "type": "Point", 
        "coordinates": [149.522, -30.3603]},
        "properties": {
            "id": "20447637",
            "lat": "-30.3603", 
            "long": "149.522", 
            "timestamp": "1450247155", 
            "strokeType": "0", 
            "mag": "19.9"
        }
    },
{"type": "Feature",
    "geometry": {
        "type": "Point", 
        "coordinates": [149.555, -30.3647]},
        "properties": {
            "id": "20451255",
            "lat": "-30.3647", 
            "long": "149.555", 
            "timestamp": "1450247646", 
            "strokeType": "3", 
            "mag": "0"
        }
    },...

我目前正在使用對PHP腳本的ajax調用導入此geojson文件,該腳本從數據庫生成所需的數據,這一切都很好,而且反應靈敏。 問題是,當我嘗試對這些項目進行樣式設置時,可能會導致瀏覽器崩潰(其中可能有數千個)。 這是我目前用來設置樣式的代碼:

function styleFeature(feature) {
    var seconds = new Date().getTime() / 1000;
    var timeElapsed = seconds - feature.getProperty('timestamp');
    var fraction = timeElapsed/(TimeScale/255);
    var color = 'rgb(' + Math.round((255 - fraction)) + ', 0, ' + Math.round(0 + fraction) + ')';
    if(timeElapsed<15) { var stkWeight = 2; var stkColor = "#000"; } else { var stkWeight = 0.5; var stkColor = "#fff"; }
    if(feature.getProperty('strokeType')==0) {
        if(feature.getProperty('mag')>0) {
            return {
                icon: {
                    path: 'm5.219986,29.697235l23.795303,0l0,-25.117241l24.409424,0l0,25.117241l23.795288,0l0,25.765518l-23.795288,0l0,25.117264l-24.409424,0l0,-25.117264l-23.795303,0l0,-25.765518z',
                    strokeWeight: stkWeight,
                    strokeColor: stkColor,
                    fillColor: color,
                    fillOpacity: 0.5,
                    scale: 0.12 * scale
                },
            };
        } else {
            return {
                icon: {
                    path: google.maps.SymbolPath.BACKWARD_OPEN_ARROW,
                    strokeWeight: stkWeight,
                    strokeColor: stkColor,
                    fillColor: color,
                    fillOpacity: 0.5,
                    scale: 1.5 * scale
                },
            };
        }
    } else {
        return {
            icon: {
                path: google.maps.SymbolPath.CIRCLE,
                strokeWeight: stkWeight,
                strokeColor: stkColor,
                fillColor: color,
                fillOpacity: 0.5,
                scale: 2 * scale
            },
        };
    }
}

有3種不同類型的圖標,其中兩種是Google的默認圖標,而一種是“自定義+形狀”。 geojson文件中的每個要素的樣式如下:

  • 圖標的顏色取決於其時間戳(紅色為當前,藍色為舊)
  • “ strokeType”和“ mag”字段確定要使用的圖標(圓形,三角形,加號)
  • 在過去的x秒內,新圖標帶有較粗的黑色邊框

這都是從map.data.setStyle(styleFeature);調用的map.data.setStyle(styleFeature); 直接在map.data.addGeoJson(geoJSONDataFromAjaxCall);

然后每x秒調用此腳本以檢索更新的信息,然后還需要將該信息與其他信息一起繪制在地圖上。 需要刪除早於預定時間(例如60分鍾或3600秒)的數據,並且每個標記都需要隨着時間的推移而改變其顏色。

我已經能夠實現上述所有目的,但是,當視口中有數百個圖標時,瀏覽器將被阻塞並可能崩潰。 如果我使用標准標記而不設置樣式,則效果很好。 我正在尋找一種樣式設置這些圖標而不會使瀏覽器崩潰的方法,我想我這樣做的方法會占用大量資源。

一旦對象(例如圓圈標記圖標)的數量達到1k或更高,就可能發生此行為,性能將大大下降。 通常,在這種情況下,建議通過畫布圖塊疊加來渲染對象。

為此,讓我們介紹一個用於顯示標記圖標自定義疊加層

資料來源: iconsoverlay.js

這是一個類似的示例,演示了如何加載GeoJSON數據並顯示帶有自定義圖標的標記:

 function initMap() { var map = new google.maps.Map(document.getElementById('map'), { center: { lat: -30.3647, lng: 149.555 }, zoom: 4, mapTypeId: google.maps.MapTypeId.TERRAIN }); var overlay = new IconsOverlay(map); //1.load GeoJSON data var data = generateData(1000); //2.display custom icons data.features.forEach(function (f, id) { var position = new google.maps.LatLng(f.geometry.coordinates[1], f.geometry.coordinates[0]); if (id > 0 && id % 2 == 0) { //add circle icon var circleIconProperties = { id: id, path: google.maps.SymbolPath.CIRCLE, strokeWeight: 2, strokeColor: 'rgba(0, 0, 0, 1)', fillColor: 'rgba(160,16,0,0.5)', scale: 10 } overlay.addIcon(position, circleIconProperties); console.log(id); } else if (id > 0 && id % 3 == 0) { //add path icon var pathIconProperties = { id: id, path: 'm5.219986,29.697235l23.795303,0l0,-25.117241l24.409424,0l0,25.117241l23.795288,0l0,25.765518l-23.795288,0l0,25.117264l-24.409424,0l0,-25.117264l-23.795303,0l0,-25.765518z', strokeWeight: 2, strokeColor: 'rgba(0, 0, 0, 1)', fillColor: 'rgba(160,16,0,0.5)', scale: 0.4 } overlay.addIcon(position,pathIconProperties); } else { var arrowIconProperties = { id: id, path: google.maps.SymbolPath.BACKWARD_OPEN_ARROW, strokeColor: 'rgba(0, 0, 0, 1)', fillColor: 'rgba(160,16,0,0.5)', fillOpacity: 0.5, scale: 4 } overlay.addIcon(position, arrowIconProperties); } }); } //Helper methods function generateData(count) { var data = { "type": "FeatureCollection", "features": [] }; for (var i = 0; i < count; i++) { var lat = getRandomArbitrary(-30.0,-15.0); var lng = getRandomArbitrary(120.0,150.0); data.features.push({ "type": "Feature", "geometry": { "type": "Point", "coordinates": [lng, lat] }, "properties": { "id": i.toString(), "lat": lat.toString(), "long": lng.toString(), } }); } return data; } function getRandomArbitrary(min, max) { return Math.random() * (max - min) + min; } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } google.maps.event.addDomListener(window, 'load', initMap); 
 html, body { height: 100%; margin: 0; padding: 0; } #map { height: 100%; } 
 <script src="https://maps.googleapis.com/maps/api/js"></script> <script type="text/javascript" src="http://rawgit.com/vgrem/6dd435ebacd720f0ad10/raw/4af8287e17c3aea92b50681d0a9061f2b620f70d/iconsoverlay.js"></script> <div id="map"></div> 

演示頁面

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM