The relative path in Vue single file components does not work properly

Viewed 3208

So recently I am doing a small challenge with Vue.js and OpenLayers 5.

The first step I want to do is create a simple Open street map and put my own GPS data as vector layer onto it.

Things are going well until I got some issue with the "path" in Vue.js single file component.

Below is what the child component looks like (for the GPS vector layer generation):

<template>
  <div>
      <input type="button" value="addGPXData" @click="addData"/>
  </div>
</template>

<script>
import Map from 'ol/Map.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from 'ol/style.js';
import VectorSource from 'ol/source/Vector.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import GPX from 'ol/format/GPX.js';

export default {
  name: 'addGPXData',
  props: ['map'],
  data () {
    return {

    }
  },
  mounted () {

  },
  methods: {
    addData: function() {
        console.log('addData_map: ', this.map);

        var style = {
            'Point': new Style({
                image: new CircleStyle({
                    fill: new Fill({
                        color: 'rgba(255,255,0,0.4)'
                    }),
                    radius: 5,
                    stroke: new Stroke({
                        color: '#ff0',
                        width: 1
                    })
                })
            }),
        };

        var vector = new VectorLayer({
            source: new VectorSource({
                //url: '.././assets/2018-08-05_17-22-37.gpx',
                //url: '.././assets/test.gpx',
                url: 'https://openlayers.org/en/v4.6.2/examples/data/gpx/fells_loop.gpx',
                crossOrigin: 'anonymous',
                format: new GPX()
            }),
            style: style['Point']
        });

        this.map.addLayer(vector);
    }
  }
}
</script>

Please notice the three lines of URL in VectorSource

The line I left there is the only URL (with https://) that works, it is an URL from OpenLayers itself for the example and demo.

I downloaded the .gpx file from the official and renamed it to test.gpx together with my own GPS file 2018-08-05_17-22-37.gpx. I put them to the default assets folder. The structure of my file system seems like this (I didn't change it, it was originally created by Vue-cli):

--src
  --assets
    --2018-08-05_17-22-37.gpx
    --test.gpx
  --components
    --addGPXData.vue
    --mapContainer.vue
  --App.vue
  --main.js

I would like to know what is wrong with these two lines of URL which I commented out? I have read the official document and I understand for those situations, a relative path, which begins with "." need to be used. I did that, but it still doesn't work. How should I write the path for local files?

The official document for the static assets and path:

https://cli.vuejs.org/guide/html-and-static-assets.html#static-assets-handling

update:

I have already tried the given advises, thank you for all you guys that helped, but nothing works at the moment. either ../, @ or import

and I started to read the document of OpenLayers, which I find, quite interesting:

OpenLayers will the URL and make an XMLHttpRequest to load the GPX file. And I think that is the problem here. Because I think we can't make XMLHttpRequest in Vue to get a local file. Because all the files will be compiled first and at the end, we don't have a path like '../asset/x.gpx'.

I don't know if I understand that right. I would also ask what will the file system look like after it all being compiled?

The final update

Today I solved this problem by putting the GPX file to the public folder and use Vue-resource (GET) to get it, the codes look like below:

    // get the GPX file
    this.$http.get(self.selectedGPX + '.gpx').then(response => {
        var GPXString = response.body;
    }, response => {
        //error callback
        console.log('Http request get error');
    });

on the OpenLayers side, I just used the solution 2 from the question which is marked as duplicated. I no more use the URL option and choose to load the GPX file with Vue-resource as String and parse it, at the end add the parsed features to the empty vector layer.

2 Answers

Your component is nested one folder deep (/components/addGPXData.vue), so you need only ../ to get back to /assets directory. From my understanding your url has to be ../assets/2018-08-05_17-22-37.gpx

I think you can solve this importing the file:

    import gpx from '../assets/2018-08-05_17-22-37.gpx',

    var vector = new VectorLayer({
        source: new VectorSource({
            url: gpx,
            crossOrigin: 'anonymous',
            format: new GPX()
        }),
        style: style['Point']
    });

Make sure that webpack is using file-loader on gpx files.

on your vue.config.js:

module.exports = {
  configureWebpack: {
    module: {
        rules: [{
            test: /\.gpx$/i,
            use: [{
                loader: 'file-loader'
            }]
        }]
    }
  }
}
Related