199.Vue3 + OpenLayers 实现:点击 / 拖动地图播放音频

一、效果说明

本文将实现一个有趣的小功能:

  • 🖱️ 点击地图 → 播放点击音效

  • 🗺️ 拖动地图 → 播放循环音效

  • ⛔ 停止拖动 → 停止音效

适用于:

  • GIS系统交互增强

  • 无人机巡检系统

  • 可视化项目体验优化


二、技术栈

  • Vue3(Composition API)

  • OpenLayers

  • 原生 Audio API


三、实现思路

核心逻辑非常简单:

操作 触发事件 行为
点击地图 click 播放音效
开始拖动 movestart 播放循环音效
结束拖动 moveend 停止音效

四、完整代码

javascript 复制代码
<!--
 * @Author: 彭麒
 * @Date: 2026/3/30
 * @Email: 1062470959@qq.com
 * @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
 -->
<template>
  <div class="container">
    <div class="w-full flex justify-center flex-wrap">
      <div class="font-bold text-[24px]">
        Vue3 + Openlayers:点击/拖动播放音频
      </div>
    </div>
    <div id="map"></div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import 'ol/ol.css'
import { Map, View } from 'ol'
import Tile from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'

const map = ref(null)

const clickAudio = new Audio('https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3')
const moveAudio = new Audio('https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3')

// 循环播放(拖动用)
moveAudio.loop = true

const initMap = () => {
  const raster = new Tile({
    source: new XYZ({
      url: 'https://www.google.com/maps/vt?lyrs=m&gl=en&x={x}&y={y}&z={z}',
      crossOrigin: 'anonymous'
    })
  })

  map.value = new Map({
    target: 'map',
    layers: [raster],
    view: new View({
      projection: 'EPSG:3857',
      center: [2617200, 5951081],
      zoom: 5
    })
  })

  // ✅ 点击播放音效
  map.value.on('click', () => {
    clickAudio.currentTime = 0 // 关键:支持连续点击
    clickAudio.play()
  })

  // ✅ 开始拖动
  map.value.on('movestart', () => {
    if (moveAudio.paused) {
      moveAudio.currentTime = 0
      moveAudio.play()
    }
  })

  // ✅ 拖动结束
  map.value.on('moveend', () => {
    moveAudio.pause()
    moveAudio.currentTime = 0
  })
}

onMounted(() => {
  initMap()
})
</script>

<style scoped>
.container {
  width: 840px;
  height: 590px;
  margin: 50px auto;
  border: 1px solid #42b983;
}

#map {
  width: 800px;
  height: 460px;
  margin: 0 auto;
  border: 1px solid #42b983;
}
</style>

五、关键知识点解析

1️⃣ Vue3 Composition API

复制代码
const map = ref(null)
  • 使用 ref 替代 data

  • 使用 onMounted 替代 mounted


2️⃣ OpenLayers 事件机制

复制代码
map.value.on('click', handler)
map.value.on('movestart', handler)
map.value.on('moveend', handler)

说明:

  • click:点击地图

  • movestart:开始拖动

  • moveend:拖动结束


3️⃣ Audio API 使用

复制代码
const audio = new Audio('xxx.mp3')
audio.play()
audio.pause()

六、常见问题

❗ 1. 连续点击没有声音

复制代码
clickAudio.currentTime = 0

👉 必须重置播放时间


❗ 2. 音频叠加播放

复制代码
if (moveAudio.paused)

👉 防止重复触发播放


❗ 3. 浏览器不播放音频

原因:

  • 浏览器限制自动播放

  • 必须用户交互(点击/拖动)

👉 本案例已符合要求 ✔


❗ 4. 报错:NotSupportedError

复制代码
The element has no supported sources

原因:

  • 音频链接失效

  • 被跨域拦截

  • 不是 MP3 文件

👉 建议:

✔ 使用本地音频

✔ 或使用稳定 HTTPS 音频资源


七、进阶优化

✅ 1. 使用本地音频(生产环境)

复制代码
import clickMp3 from '@/assets/audio/click.mp3'

const clickAudio = new Audio(clickMp3)

✅ 2. 封装音频 Hook

复制代码
const useAudio = () => {
  const play = (audio) => {
    audio.currentTime = 0
    audio.play()
  }
  return { play }
}

✅ 3. 场景升级(推荐方向)

  • 🚁 无人机飞行音效

  • 📡 雷达扫描音

  • 📢 AI语音播报


八、总结

本文实现了一个简单但非常实用的功能:

👉 让地图"有声音"

提升点:

  • 交互更真实

  • 系统更有沉浸感

  • 非常适合 GIS / 可视化系统


九、后续拓展

如果你正在做:

  • 巡检系统

  • 三维 GIS(Cesium)

  • 数字孪生

👉 可以进一步结合:

  • 空间音效

  • 事件驱动音频

  • 语音播报系统


如果觉得有帮助,欢迎点赞 👍 收藏 ⭐ 关注 🚀

后续会持续更新 Vue3 + GIS 实战内容!

相关推荐
牛奔4 分钟前
mise 管理多版本 Go 项目
开发语言·前端·chrome·后端·golang
志尊宝31 分钟前
Vue3 零基础每日笔记(076):防抖节流的正确使用——搜索框、按钮防重复提交、滚动监听
javascript·vue.js·笔记
VidDown35 分钟前
上传 2GB 文件别让 Django 接:分片上传、对象存储直传与秒传
python·django·音视频·状态模式·实时音视频·视频编解码·视频
顽疲44 分钟前
从零用 Java 实现小红书 SpringBoot Vue UniApp(23)笔记话题多对多:一条笔记进多个话题池
java·vue.js·spring boot
能源革命1 小时前
Vue 网格拖拽布局组件全景指南:7 大方案深度对比
前端·javascript·vue.js
阿明副业观察1 小时前
AI视频生成工具功能与作用全面解析:赋能高效内容创作
大数据·人工智能·aigc·音视频·ai写作
PC2005_cloud1 小时前
AI 汉字漂移实录:它为什么总把「学习」写成日语「学習」
前端·后端
穆梓兰煊1 小时前
AI供应链安全不再只是包安全,还涉及模型与数据
前端·数据库
RaaS1001 小时前
AI网关能做Prompt注入防护吗?AI网关核心功能详解
前端·后端
deli0072 小时前
Skill 怎么写才被 Agent 命中?18 条规则做成 SKILL.md 校验器,规范样例 92 分
前端