基于 Laravel + Vue 构建 API 驱动的前后端分离应用系列(十七) —— 在高德地图上自定义咖啡店点标记图标并显示信息窗体

上一篇教程中我们已经成功将咖啡店显示到高德地图中,除此之外,我们还可以基于高德地图提供的 JS API 实现更多的高级功能,比如自定义点标记图标,点击点标记图标展示信息窗体等,本篇教程我们将以这两个案例为例进行演示,希望可以抛砖引玉,帮助你快速学会如何使用高德地图 JS API 实现自己需要的高级功能。

自定义点标记图标

在开始之前,你可以快速浏览下高德地图自定义点标记的 JS API 文档:https://lbs.amap.com/api/javascript-api/reference/overlay#marker,其中定义了多种自定义点标记的实现方式,最简单的就是通过 Marker 对象的 icon 字段传递图标 URL 进行设置,这里我们使用第二种方式,基于 Icon 对象进行设置。

首先我们去这里下载一个地图图标:https://www.iconfinder.com/icons/118702/fill_map_pin_icon#size=128,存储到 storage/app/public/img 目录下,另存为 coffee-marker.png,然后通过如下 Artisan 命令:

php artisan storage:link

public 目录下创建一个软链接 storage 指向 storage/app/public,这样就可以通过 Web URL 访问 storage/app/public 目录下的文件。

准备好图片和访问目录后,打开 resources/assets/js/config.js,新增全局变量 ROAST_CONFIG.APP_URL

var api_url = '';
var app_url = '';
var gaode_maps_js_api_key = '33c20882595f1fecc2d31c8c73a38da7';

switch( process.env.NODE_ENV ){
    case 'development':
        api_url = 'http://roast.test/api/v1';
        app_url = 'http://roast.test';
        break;
    case 'production':
        api_url = 'http://roast.demo.laravelacademy.org/api/v1';
        app_url = 'http://roast.demo.laravelacademy.org';
        break;
}

export const ROAST_CONFIG = {
    API_URL: api_url,
    APP_URL: app_url,
    GAODE_MAPS_JS_API_KEY: gaode_maps_js_api_key
};

然后打开 resources/assets/js/components/cafes/CafeMap.vue 文件,引入上述 config.js 配置文件:

import {ROAST_CONFIG} from '../../config.js';

编辑 buildMarkers 方法如下,:

buildMarkers() {
    // 初始化点标记数组
    this.markers = [];

    // 自定义点标记图标
    var image = ROAST_CONFIG.APP_URL + '/storage/img/coffee-marker.png';
    var icon = new AMap.Icon({
        image: image,  // 图像 URL
        imageSize: new AMap.Size(19, 33)  // 设置图标尺寸
    });

    // 遍历所有咖啡店创建点标记
    for (var i = 0; i < this.cafes.length; i++) {

        // 为每个咖啡店创建点标记并设置经纬度
        var marker = new AMap.Marker({
            position: AMap.LngLat(parseFloat(this.cafes[i].latitude), parseFloat(this.cafes[i].longitude)),
            title: this.cafes[i].name,
            icon: icon,  // 通过 icon 对象设置自定义点标记图标来替代默认蓝色图标
        });

        // 将点标记放到数组中
        this.markers.push(marker);
    }

    // 将所有点标记显示到地图上
    this.map.add(this.markers);
},

运行 npm run dev 重新构建前端资源后,再次访问之前的 Cafes 页面,就可以看到之前默认的蓝色图标已经被替换为自定义的图标了:

信息窗体创建及点击展示事件

接下来我们来实现点击点标记图片显示信息窗体的功能,信息窗体可以提供关于这个咖啡店的更多信息,比如电话、详细地址、特色服务、图片评价等,作为演示,我们仅仅展示咖啡店名称,你可以通过 HTML 片段显示更多信息。

开始之前,还是建议快速浏览下高德地图提供的 API 文档:https://lbs.amap.com/api/javascript-api/guide/overlays/infowindow,和点标记一样,我们在 resources/assets/js/components/cafes/CafeMap.vue 定义一个 infoWindows 数组对象用来存放所有的信息窗体:

data() {
    return {
        markers: [],
        infoWindows: []
    }
},

然后在遍历咖啡店创建点标记的循环体中为每个咖啡店创建信息窗体,将其推送到 infoWindows 数组中,并未 marker 对象绑定点击事件处理函数,当点击点标记时,显示其对应的信息窗体:

// 遍历所有咖啡店创建点标记
for (var i = 0; i < this.cafes.length; i++) {

    // 为每个咖啡店创建点标记
    var marker = new AMap.Marker({
        position: AMap.LngLat(parseFloat(this.cafes[i].latitude), parseFloat(this.cafes[i].longitude)),
        title: this.cafes[i].name,
        icon: icon,
        map: this.map
    });

    // 为每个咖啡店创建信息窗体
    var infoWindow = new AMap.InfoWindow({
        content: this.cafes[i].name
    });
    this.infoWindows.push(infoWindow);

    // 绑定点击事件到点标记对象,点击打开上面创建的信息窗体
    marker.on('click', function () {
        infoWindow.open(this.getMap(), this.getPosition());
    });

    // 将点标记放到数组中
    this.markers.push(marker);
}

至此,我们就完成了信息窗体创建及绑定到点标记点击事件处理器的代码,运行 npm run dev 重新编译前端资源,再次访问 Cafes 页面,点击咖啡店标记,就可以看到信息窗体显示出来了:

注:本项目源代码存放在 Github 上: nonfu/roastapp

学院君 has written 1043 articles

Laravel学院院长,终身学习者

积分:125952 等级:P12 职业:手艺人 城市:杭州

5 条回复

  1. 方石 方石 says:

    标记不上啊。查了一下,是这条语句 position: AMap.LngLat(parseFloat(this.cafes[i].latitude), parseFloat(this.cafes[i].longitude)), , this.cafes[i].latitude 取不到值。奇怪 。

登录后才能进行评论,立即登录?