如何突出显示在我的传单地图(nuxt/vue)中单击了哪个标记
Posted
技术标签:
【中文标题】如何突出显示在我的传单地图(nuxt/vue)中单击了哪个标记【英文标题】:How can I highlight which marker has been clicked in my leaflet map (nuxt/vue) 【发布时间】:2021-04-23 00:44:19 【问题描述】:我有一张传单地图,上面显示了一个地区的不同餐厅和远足径。 当用户单击标记时,我会在下面的 div 中显示有关它的信息。
但是,如果当您单击标记时,它会在地图上突出显示自己,这样您就可以准确地看到您当前正在阅读的标记,这将是一个很好的用户体验。
但是我似乎找不到办法。
标记是通过使用 v-for 循环通过“位置”对象的 JSON 文件创建的,JSON 示例:
"locations":
"restaurants": [
"id": "R1",
"name": "El Rancho Grande",
"latlong": [
"36.90316216998795",
"-4.115129907833307"
],
"type": "Restaurant",
"description": "This is a description of the location",
"img": "https://www.viewranger.com/routelibrary/discoverywalks/axarquia/0115.jpg"
...
在我看来,一种方法可能是:
创建所有标记并添加到数组中。
将它们全部添加到地图中。
当一个被点击时,在数组中找到那个标记,更新它的图标以显示它当前被选中。
删除所有标记。
用现在更新的标记重新绘制它们。
但是这种方法似乎太过分了,所以我对此表示怀疑。
谁能给我一些想法?干杯!
这是我在“了解该地区”页面中的地图:
...
<!-- ############# INTERACTIVE MAP ############# -->
<div class="area__map">
<div id="map-wrap">
<no-s-s-r>
<l-map :zoom="13" :center="[36.9023, -4.1139]" ref="map">
<l-tile-layer
url="http://s.tile.osm.org/z/x/y.png"
></l-tile-layer>
<!-- ############# CREATE RESTAURANT MARKERS ############# -->
<l-marker
v-for="restaurant in restaurants"
:key="restaurant.id"
:lat-lng="restaurant.latlong"
:icon="eatIcon"
v-on:click="getPin(restaurant.id)"
></l-marker>
<!-- ############# CREATE HIKING TRAIL MARKERS ############# -->
<l-marker
v-for="walk in walks"
:key="walk.id"
:lat-lng="walk.latlong"
:icon="walkIcon"
v-on:click="getPin(walk.id)"
></l-marker>
</l-map>
</no-s-s-r>
</div>
<!-- ############# SHOW CURRENT SELECTED MARKER INFO ############# -->
<div class="area__map__selected-pin">
<h3> selectedPin.name </h3>
<h4> selectedPin.type </h4>
<p> selectedPin.description </p>
<img
v-if="selectedPin.img != ''"
:src="selectedPin.img"
class="area__map__selected-pin__selected-img"
/>
</div>
<div class="area__subheader triangle triangle-yellow"></div>
</div>
</template>
<script>
import json from '@/static/json/locations.json'
import latLng, icon from 'leaflet'
export default
name: 'Area',
data: function ()
return
// ############# INTRO VIDEO SETTINGS #############
videoLanguage: 'English',
englishSrc: 'https://www.youtube.com/embed/lRKmJqDbVsY',
spanishSrc: 'https://www.youtube.com/embed/q0WkEkIMmQo',
currentSrc: 'https://www.youtube.com/embed/lRKmJqDbVsY',
// ############# IMAGE GALLERY SETTINGS #############
swiperOption:
grabCursor: true,
loop: true,
autoplay:
delay: 5000,
disableOnInteraction: false,
,
pagination:
el: '.swiper-pagination',
,
map: this.$refs.map,
,
// ############# ARRAY TO STORE GALLERY IMAGES #############
images: [],
locations: json.locations,
// ############# ARRAY TO STORE RESTAURANT OBJECTS #############
restaurants: [],
// ############# ARRAY TO STORE HIKING TRAIL OBJECTS #############
walks: [],
// ############# LEAFLET HIKING TRAIL MARKER ICON #############
walkIcon: icon(
iconUrl: '/MapMarkers/hiking.png',
iconSize: [20, 20],
iconAnchor: [16, 37],
),
// ############# LEAFLET RESTAURANT MARKER ICON #############
eatIcon: icon(
iconUrl: '/MapMarkers/restaurant.png',
iconSize: [20, 20],
iconAnchor: [16, 37],
),
// ############# STORE THE CURRENTLY SELECTED LOCATION DATA #############
selectedPin:
name: 'Please click on a map pin for more information',
,
,
// ############# IMPORT THE IMAGES ON MOUNT #############
mounted()
this.importImages(require.context('~/assets/AreaPictures/', true))
this.importLocations(this.locations)
console.log(this.fas)
,
methods:
changeSrc()
if (this.videoLanguage === 'English')
this.currentSrc = this.englishSrc
else
this.currentSrc = this.spanishSrc
,
// ############# IMPORT GALLERY IMAGES #############
importImages(r)
r.keys().forEach((key) =>
var path = key.substring(1) //-----THE PATH FOR SOME REASON CONTAINS A . SO I REMOVE IT
this.images.push(
imageURL: path, //----- CREATE A NEW OBJECT AND ADD IT TO IMAGES
)
)
,
// ############# SPLIT JSON DATA INTO RESTAURANT AND HIKING TRAIL ARRAYS #############
importLocations()
this.restaurants = this.locations.restaurants
this.walks = this.locations.walks
,
// ############# FIND THE DATA OF THE CURRENTLY SELECTED MAP MARKER BY USING ITS ID #############
getPin(id)
let item
if (id.includes('W'))
for (let i = 0; i < this.walks.length; i++)
item = this.walks[i]
if (item.id === id)
this.selectedPin = item
else if (id.includes('R'))
for (let i = 0; i < this.restaurants.length; i++)
item = this.restaurants[i]
if (item.id === id)
this.selectedPin = item
else
window.alert('Error, no info on marker found')
,
,
</script>
<style lang="scss">
...
编辑: 上下文图片
【问题讨论】:
【参考方案1】:我的建议是:
当一个标记被选中时,给 html 元素添加一个类,它会添加一个投影,并缩放图标:
.markerSelected
transform: scale(1.5);
filter: drop-shadow(0px 0px 10px rgba(0,0,0,.5));
另外,为了捕获事件,我建议使用事件冒泡。为此,请将您的@click
添加到父元素,然后使用event.target
找到单击的图标。
一旦您发出了事件,请将 selectedId
数据参数设置为所选项目的 ID。我在这里假设walking vs restaurant id 是独一无二的,不会有冲突。
然后,按如下方式更新 HTML:
<l-marker
v-for="restaurant in restaurants"
:key="restaurant.id"
:lat-lng="restaurant.latlong"
:icon="eatIcon"
:class="restaurant.id === selectedId ? 'markerSelected' : ''"
></l-marker>
阅读:Event.Target
这里还有另一个好帖子:How to bubble events in vue
【讨论】:
非常感谢您的回复。所以根据我的理解,你推荐使用 $emit?它将向父级发送事件。 我已经实现了这个,我可以从标记调用一个函数到父级,但是我对如何将该类添加到标记感到困惑。另外,如果用户单击另一个标记,我如何将其从标记中删除并将其添加到另一个标记中 您可以向l-marker
添加一个响应式类。我已经添加到上面的回复中以上是关于如何突出显示在我的传单地图(nuxt/vue)中单击了哪个标记的主要内容,如果未能解决你的问题,请参考以下文章