195.Vue3 + OpenLayers:监听瓦片地图加载情况(200、403及异常处理)

一、前言

效果:

在实际项目开发中,尤其是无人机巡检系统、GIS系统等场景中,地图瓦片的加载稳定性非常关键。

我们经常会遇到这些问题:

  • 瓦片加载失败(白块)

  • 接口返回 403(无权限 / 被限制)

  • 网络异常导致地图不完整

  • 部分区域加载异常但无提示

👉 默认情况下,OpenLayers 并不会暴露 HTTP 状态码,这就导致我们无法感知真实的加载状态。

所以这篇文章的核心就是:

如何在 Vue3 + OpenLayers 中监听瓦片加载状态,并对 200、403、异常等情况进行处理


二、核心思路

OpenLayers 提供了一个关键能力:

复制代码
source.setTileLoadFunction()

通过重写这个方法,我们可以:

✅ 接管瓦片加载流程

✅ 自定义请求方式(XHR / fetch)

✅ 获取 HTTP 状态码

✅ 做统一异常处理


三、完整示例代码(Vue3 + Composition API)

javascript 复制代码
<!--
 * @Author: 彭麒
 * @Date: 2026/3/24
 * @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:监听瓦片地图加载情况,200,403,及其他状态码的处理
      </div>
    </div>
    <div id="vue-openlayers"></div>
    <div class="dialog" v-show="isOpen">
      出错了,出错了! <br />
      <span @click="close">关闭</span>
    </div>
  </div>
</template>

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

// 状态
const map = ref(null)
const mysource = ref(null)
const isOpen = ref(false)

// 关闭弹窗
const close = () => {
  isOpen.value = false
}

// 监听瓦片状态
const getStatus = () => {
  mysource.value.setTileLoadFunction((tile, src) => {
    const xhr = new XMLHttpRequest()
    xhr.responseType = 'blob'

    xhr.addEventListener('loadend', (evt) => {
      const status = evt.currentTarget.status
      const data = evt.currentTarget.response

      if (status === 200) {
        tile.getImage().src = URL.createObjectURL(data)
      } else if (status === 403) {
        console.log(status)
        isOpen.value = true
      } else {
        tile.setState(TileState.ERROR)
      }
    })

    xhr.addEventListener('error', () => {
      isOpen.value = true
      tile.setState(TileState.ERROR)
    })

    xhr.open('GET', src)
    xhr.send()
  })
}

// 初始化地图
const initMap = () => {
  mysource.value = 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: 'vue-openlayers',
    layers: [
      new TileLayer({
        source: mysource.value
      })
    ],
    view: new View({
      projection: 'EPSG:4326',
      center: [-100.15, 16.79],
      zoom: 5
    })
  })
}

// 生命周期
onMounted(() => {
  initMap()
  getStatus()
})
</script>

<style scoped>
.container {
  width: 840px;
  height: 570px;
  margin: 50px auto;
  border: 1px solid #42B983;
  position: relative;
}

#vue-openlayers {
  width: 800px;
  height: 450px;
  margin: 0 auto;
  border: 1px solid #42B983;
  position: relative;
}

.dialog {
  width: 600px;
  height: 100px;
  background: #FF0000;
  position: absolute;
  left: 120px;
  top: 150px;
  padding: 30px 30px 0;
}
</style>

四、关键代码解析

1️⃣ setTileLoadFunction(核心入口)

复制代码
mysource.value.setTileLoadFunction((tile, src) => {})

👉 作用:拦截默认瓦片加载行为

默认是 <img src=xxx>

现在变成 👉 我们自己发请求


2️⃣ 为什么用 XMLHttpRequest?

复制代码
const xhr = new XMLHttpRequest()

原因:

  • 可以拿到 status

  • 可以处理 error

  • 支持 blob 数据

⚠️ 注意:

fetch 虽然更现代,但在 OpenLayers 中,XHR 更稳定


3️⃣ 处理 200 状态

复制代码
tile.getImage().src = URL.createObjectURL(data)

👉 手动把 blob 转成图片


4️⃣ 处理 403(重点)

复制代码
if (status === 403) {
  isOpen.value = true
}

常见原因:

  • 地图服务未授权

  • key 失效

  • 被限流

  • 跨域问题


5️⃣ 处理异常

复制代码
tile.setState(TileState.ERROR)

👉 告诉 OpenLayers:这个瓦片加载失败

否则会一直卡住


五、实际项目中的优化建议(重点)

✅ 1. 防止弹窗疯狂触发

现在代码是:

复制代码
isOpen.value = true

👉 实际项目建议:

复制代码
if (!isOpen.value) {
  isOpen.value = true
}

✅ 2. 增加重试机制

复制代码
let retry = 0
const maxRetry = 2

失败自动重试,提高稳定性


✅ 3. 多地图源降级(非常重要)

复制代码
主地图(Google) → 失败 → 切换天地图 / 高德

👉 企业级项目必须做!


✅ 4. 错误提示升级

不建议用:

复制代码
<div class="dialog">

建议:

  • ElMessage

  • 全局 Toast

  • 或埋点上报


六、关于 403 的本质问题(很多人踩坑)

你当前使用的是:

复制代码
https://www.google.com/maps/vt

⚠️ 注意:

在国内或部分网络环境下:

👉 403 是正常现象

原因:

  • 无 API Key

  • 被限制访问

  • 网络策略问题


七、适用场景

这套方案非常适合:

  • 无人机巡检系统

  • WebGIS 平台

  • 数字孪生系统

  • 地图大屏项目


八、总结

本文核心就一句话:

通过 setTileLoadFunction 接管瓦片请求,从而实现对 HTTP 状态码的精细控 你获得了:

✅ 监听 200 / 403 / error

✅ 控制瓦片加载流程

✅ 提升地图稳定性

✅ 支持企业级扩展

相关推荐
给钱,谢谢!2 小时前
记录uni-app Vue3 慎用 Teleport,会导致页面栈混乱
前端·vue.js·uni-app
陈天伟教授2 小时前
人工智能应用- AI 增强显微镜:01.显微镜的瓶颈
前端·人工智能·安全·xss·csrf
Mintopia2 小时前
Pencil.dev 设计 → 规格 → 代码 → 校验
前端·人工智能
TON_G-T2 小时前
深入学习webpack-tapable
前端·学习·webpack
工边页字2 小时前
AI产品面试题:什么是 Function Calling?
前端·人工智能·后端
Mintopia2 小时前
一份合格的软件 VI 文字文档简单版
前端·css·人工智能
四千岁2 小时前
如何精准统计 Token 消耗,使用对账工具控制成本?
前端·javascript·vue.js
开心码农1号2 小时前
前端web页面请求后端服务时,接口出现50s初始连接超时
前端
jiayong232 小时前
0基础学习VUE3 第 3 课:任务页怎么把列表、筛选、表单、弹窗串起来
前端·javascript·学习