Search code examples
javascriptopenlayers-3

Add GPX dynamically with openlayers


I am trying to show different routes from gpx files by selecting them from checkboxes, but the vector layer doesn't appear.

I used as a guide the examples from OpenLayers webpage: GPXDATA and DragandDrop without results.

Main.php

<!DOCTYPE html>
<html>
<head>
    <title>Mapa simple de OpenStreetMap con Open Layers</title>    
    <link rel="stylesheet" href="https://openlayers.org/en/v4.0.1/css/ol.css" type="text/css">
    <script src="https://openlayers.org/en/v4.0.1/build/ol.js"></script>
    <link rel="stylesheet" href="css/main.css" type="text/css">
    <script src="js/main.js"></script>
</head>
<body>
    <h1 id="maintitle">Rutas de Limpieza</h1>
    <div id="content">
        <div id="menu">
            <ul>
                <li>Mostrar Rutas</li>
                <ul>Rutas de Barredoras
                    <li><input id="r1" name="ba_r1" type="checkbox">Ruta B1</li>
                    <li><input name="ba_r2" type="checkbox">Ruta B2</li>
                    <li><input name="ba_r3" type="checkbox">Ruta B3</li>
                </ul>                    
            </ul>
            <button id="sr_btn">Mostrar Rutas Seleccionas</button>
        </div>


        <div id="map" class="map"></div>
    </div>
</body>
</html>

main.js

window.onload = function(){
var defaultStyle = {
    'Point': new ol.style.Style({
      image: new ol.style.Circle({
        fill: new ol.style.Fill({
          color: 'rgba(255,255,0,0.5)'
        }),
        radius: 5,
        stroke: new ol.style.Stroke({
          color: '#ff0',
          width: 1
        })
      })
    }),
    'LineString': new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: '#f00',
        width: 3
      })
    }),
    'Polygon': new ol.style.Style({
      fill: new ol.style.Fill({
        color: 'rgba(0,255,255,0.5)'
      }),
      stroke: new ol.style.Stroke({
        color: '#0ff',
        width: 1
      })
    }),
    'MultiPoint': new ol.style.Style({
      image: new ol.style.Circle({
        fill: new ol.style.Fill({
          color: 'rgba(255,0,255,0.5)'
        }),
        radius: 5,
        stroke: new ol.style.Stroke({
          color: '#f0f',
          width: 1
        })
      })
    }),
    'MultiLineString': new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: '#00f',
        width: 3
      })
    }),
    'MultiPolygon': new ol.style.Style({
      fill: new ol.style.Fill({
        color: 'rgba(25,120,255,0.5)'
      }),
      stroke: new ol.style.Stroke({
        color: '#00f',
        width: 1
      })
    })
};

var styleFunction = function(feature, resolution) {
    var featureStyleFunction = feature.getStyleFunction();
    if (featureStyleFunction) {
      return featureStyleFunction.call(feature, resolution);
    } else {
      return defaultStyle[feature.getGeometry().getType()];
    }
};

var map = new ol.Map({
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      })
    ],
    target: 'map',
    view: new ol.View({
      center: ol.proj.fromLonLat([2.5, 39.5]),
      zoom: 12
    })
});

var btn_sr = this.document.getElementById("sr_btn").addEventListener('click', function(){        
    var vector1 = new ol.layer.Vector({
        source: new ol.source.Vector({
          url: 'gpx/qq2.gpx',
          format: new ol.format.GPX()
        }),
        style: defaultStyle
    });

    map.addLayer(new ol.layer.Vector({
        renderMode: 'image',
        source: vector1,
        style: styleFunction
    }));
});
}

For what can I understand from API the map.addLayer function should put vector1 layer top on the layers collection and show automatically, but instead I have this error: "uncaught exception: AssertionError: Assertion failed. See https://openlayers.org/en/v4.0.1/doc/errors/#41 for details." Which means : Expected an ol.style.Style or an array of ol.style.Style.

But var defaultStyle is already an array of Styles, so I don't understand the error.

Thanks.


Solution

  • You have 2 places where you set styles in your code

    • style: defaultStyle
    • style: styleFunction

    styleFunction is working correctly (it returns a style based on the geometry type). On the contrary, defaultStyle is not working because it's not an "ol.style.Style or an array of ol.style.Style." but it's an object.

    To fix the issue, you can

    • replace style: defaultStyle with style: styleFunction.
    • if your GPX contains only points, you can use style: defaultStyle['Point']
    • if it contains only lines, you can use style: defaultStyle['LineString']