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

相关推荐
ai产品老杨4 小时前
深度解析:基于异构计算的工业级AI视频中台架构,支持GB28181/RTSP接入与X86/ARM/NPU全场景部署
人工智能·架构·音视频
禅思院4 小时前
下篇:打造可观测的异步加载防御体系
前端·架构·前端框架
RTC老炮4 小时前
音视频FEC前向纠错算法Reed-Solomon原理分析
网络·算法·架构·音视频·webrtc
|晴 天|4 小时前
Vue 3 项目错误处理实战:Vue ErrorHandler、Promise 监控、用户友好提示
前端·javascript·vue.js
Cobyte4 小时前
8.响应式系统比对:手写 SolidJS 响应式系统
前端·javascript·vue.js
IT_陈寒4 小时前
Python中的这个可变默认参数陷阱我居然又踩了
前端·人工智能·后端
qiao若huan喜4 小时前
13、webgl基本概念 + 绘制狮子座星空
前端·javascript·信息可视化·webgl
火乐暖阳851054 小时前
Vue3+Node.js
vue.js·node.js·pnpm·koa2·myslq2
之歆4 小时前
Day03_HTML 列表、表格、表单完整指南(上)
前端·html
吴声子夜歌4 小时前
Vue3——组件基础
前端·javascript·vue.js