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 实战内容!

相关推荐
FFZero17 小时前
[mpv脚本系统] (五) C层系统调用的实现: mpv client通信机制
c语言·音视频
qq4356947018 小时前
Vue01
vue.js
rising start8 小时前
七、Vue Router
前端·vue.js·router
羊羊小栈8 小时前
停车场管理系统(基于前后端Web开发)
前端·人工智能·毕业设计·大作业
用户938515635078 小时前
从JS的“坑”到TS的“墙”,再到Bun与AI:打造健壮的全栈应用
前端·javascript
jserTang8 小时前
手撕 Claude Code-7:自动压缩与记忆恢复
前端·后端
橘子星8 小时前
浅谈 TypeScript 与 Bun:现代 JavaScript 开发的利器
前端·javascript
铁皮饭盒8 小时前
Bun 的三种并发"暗器":reusePort、Worker、spawn,能硬刚 Java 吗?
前端·javascript·后端
CodeSheep8 小时前
宇树科技,即将上市!
前端·后端·程序员
潜创微科技8 小时前
2026年专业创作KVM方案服务商选型指南:技术、场景与服务的全维度评估
嵌入式硬件·音视频