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

相关推荐
lichenyang4531 小时前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen1 小时前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒1 小时前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
暴走的小呆2 小时前
Vue 2 中 Object 的变化侦测:从 getter/setter 到 Dep、Watcher、Observer
vue.js
奇奇怪怪的2 小时前
Embedding 模型 10+ 横向评测
前端
陈广亮2 小时前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰2 小时前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼2 小时前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
英勇无比的消炎药2 小时前
TinyVue v-auto-tip: 文本超长自动提示的优雅方案
vue.js
子兮曰2 小时前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust