ghettovoice / vuelayers

Web map Vue components with the power of OpenLayers
https://vuelayers.github.io/
MIT License
682 stars 228 forks source link

Question about using custom Vue Components for popups #308

Closed DanRamage closed 4 years ago

DanRamage commented 4 years ago

I've been looking at the demo but I am having trouble understanding the overlays and interactions. Here's my template:

<template>
    <b-container fluid class="h-100">
        <b-row class="h-100">
            <b-col sm="4" md="3" lg="2" xl="2" class="padding-0">
                <div v-if="features.length" class="h-100 px-3 py-2 montserat-font text-white blue-background_color sidebar-opacity">
                    <h6><span v-text="title"></span></h6>
                    <h4><span v-text="site_name"></span></h4>
                    <p class="text-left">
                        Bacteria levels can change rapidly between sampling dates. To fill in the gaps,
                        we make daily <b>Nowcast</b> of bacteria conditions. These predictions do not represent
                        swimming advisories, but provide estimates of the likelihood that bacteria conditions
                        would warrant issuing an advisory if sampling were conducted that day.
                    </p>
                    <b-button-group>
                        <b-button class="type-btn-outline-primary p-2" variant="outline-primary">Forecast</b-button>
                        <b-button class="type-btn-outline-primary p-2" variant="outline-primary">Advisory</b-button>
                    </b-button-group>
                    <p class="text-center">
                        <a href="#" class="text-white card-link">Bacteria Sources</a>
                    </p>
                    <p class="text-center">
                        <a href="#" class="text-white card-link">Locations</a>
                    </p>
                    <p class="text-center">
                        <a href="#" class="text-white card-link">About</a>
                    </p>
                </div>
            </b-col>
            <b-col sm="8" md="9" lg="10" xl="10"  ref="map_column" class="padding-0">
                <vl-map style="width: 100%; height: 100%; position:absolute" ref="site_map" :load-tiles-while-animating="true" :load-tiles-while-interacting="true" data-projection="EPSG:4326">
                    <vl-view :center.sync="center" :rotation.sync="rotation"></vl-view>
                    <vl-layer-tile>
                        <vl-source-xyz :url="layer_url" attributions="string or array" />
                    </vl-layer-tile>
                    <vl-layer-vector id="sites">
                        <vl-source-vector ref="site_vector_layer" :features.sync="features"></vl-source-vector>
                        <vl-style-box>
                            <vl-style-circle :radius="3">
                                <vl-style-fill color="white"></vl-style-fill>
                                <vl-style-stroke color="red"></vl-style-stroke>
                            </vl-style-circle>
                        </vl-style-box>
                    </vl-layer-vector>
                    <vl-interaction-select :features.sync="selectedFeatures" :layers="['sites']">
                        <vl-overlay class="feature-popup" v-for="feature in selectedFeatures" :key="feature.id" :id="feature.id"
                                    :position="pointOnSurface(feature.geometry)" :auto-pan="true" :auto-pan-animation="{ duration: 300 }">
                            <template>
                                <div>
                                    <b-card>
                                        <b-card-title>Title</b-card-title>
                                        <b-card-subtitle>SubTitle</b-card-subtitle>
                                        <b-row>
                                            <b-col>A</b-col>
                                            <b-col>B</b-col>
                                        </b-row>
                                    </b-card>
                                </div>
                            </template>
                        </vl-overlay>
                    </vl-interaction-select>
                </vl-map>
            </b-col>
        </b-row>
    </b-container>
</template>

I am just not grasping the vl-overlay functionality. Based on the type of feature that is clicked on, I want to have conditional logic to determine which of my custom vue components to use as the popup. I'm sure most of my issues stem from not being well versed in Vue. My map is populated correctly from the GeoJSON REST and the vl-interaction-select does select the point I click on. I also get the simple vl-overlay I have above, however there is no style, it is just text on the map.

Is it possible to A) use custom Vue component as a popup and B) dynamically determine which component to use?

Thanks for any help!

DanRamage commented 4 years ago

As usual, after I posted my question I figured it out. I was overthinking things. Anyway it's as simple as putting the component in.

                    <vl-interaction-select :features.sync="selectedFeatures" :layers="['sites']">
                        <vl-overlay v-for="feature in selectedFeatures"
                                    :key="feature.id"
                                    :id="feature.id"
                                    :position="feature.geometry.coordinates"
                                    :auto-pan="true"
                                    :auto-pan-animation="{ duration: 300 }">
                            <div style="background: grey">
                                <WQPopup :feature="feature"></WQPopup>
                            </div>
                        </vl-overlay>
ghettovoice commented 4 years ago

Just take a note that if you are already synchronizing selected features into your data property, then you don't. need to add vl-overlay cmp as a child of vl-interaction-select.

This will have a same result

<vl-interaction-select :features.sync="selectedFeatures" :layers="['sites']">
</vl-interaction-select>

<vl-overlay v-for="feature in selectedFeatures"
   :key="feature.id"
   :id="feature.id"
   :position="feature.geometry.coordinates"
   :auto-pan="true"
   :auto-pan-animation="{ duration: 300 }">
   <div style="background: grey">
       <WQPopup :feature="feature"></WQPopup>
    </div>
</vl-overlay>

Or with vl-overlay as child inside vl-interaction-select scoped slot this ca be

<vl-interaction-select :layers="['sites']">
 <template slot-scope="selection">
  <vl-overlay v-for="feature in selection.features"
     :key="feature.id"
     :id="feature.id"
     :position="feature.geometry.coordinates"
     :auto-pan="true"
     :auto-pan-animation="{ duration: 300 }">
     <div style="background: grey">
         <WQPopup :feature="feature"></WQPopup>
      </div>
  </vl-overlay>
  </template>
</vl-interaction-select>