当前位置: 首页 > news >正文

169.在Vue3中使用OpenLayers + D3实现地图区块呈现不同颜色的效果

一、效果展示


二、准备工作 / 前置条件

  • Node.js + npm/yarn 已安装

  • 使用 Vite 创建的 Vue 3 项目(或其它 Vue 3 脚手架)

  • 安装依赖:

npm install ol d3 # or yarn add ol d3
  • 准备 GeoJSON 文件(示例里假设文件路径为 src/assets/map/china.json 或放 public/map/china.json

提示:如果用 import chinaData from '@/assets/map/china.json',确保你的项目支持 @src 的别名(多数 Vue 项目有)。如果用 fetch,把文件放 public 目录(/map/china.json)并用 fetch('/map/china.json')


三、完整可复制的示例组件(MapColor.vue)

直接把下面文件拷贝到 src/components/MapColor.vue,并保证 china.jsonsrc/assets/map/china.json(或调整 import 路径)。

<!--* @Author: 彭麒* @Date: 2025/9/9* @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: 使用D3实现地图区块呈现不同颜色的效果</div></div><div id="vue-openlayers"></div></div>
</template><script setup>
import { ref } from "vue";
import "ol/ol.css";
import { Map, View } from "ol";
import SourceVector from "ol/source/Vector";
import LayerVector from "ol/layer/Vector";
import GeoJSON from "ol/format/GeoJSON";
import { Tile } from "ol/layer";
import XYZ from "ol/source/XYZ";
import Style from "ol/style/Style";
import Fill from "ol/style/Fill";
import Stroke from "ol/style/Stroke";
import { fromLonLat } from "ol/proj";
import * as d3 from "d3";// 引用数据
const geojsonObject = ref(null);
import {onMounted} from "vue";let map; // 地图实例// 视图
const view = new View({projection: "EPSG:3857",center: fromLonLat([122.8, 41.5]),zoom: 6,
});// 样式函数
const getStyle = () => {let colors = d3.schemeCategory10;let stroke = new Stroke({ color: "yellow", width: 1 });let randomIndex = Math.floor(Math.random() * 9);let fill = new Fill({ color: colors[randomIndex] });return new Style({ stroke, fill });
};// 初始化地图
const initMap = (geoData) => {// 在这里创建数据源const source = new SourceVector({features: new GeoJSON().readFeatures(geoData, {dataProjection: "EPSG:4326",featureProjection: "EPSG:3857",}),});map = new Map({target: "vue-openlayers",layers: [new Tile({source: new XYZ({url: "http://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",}),}),new LayerVector({source: source,style: getStyle,}),],view: view,});
};
const loadGeoJSON = async () => {try {const response = await fetch('/src/assets/map/china.json');geojsonObject.value = await response.json();// 传入实际的 GeoJSON 数据而不是 ref 对象initMap(geojsonObject.value);} catch (error) {console.error('加载GeoJSON文件失败:', error);}
};
// 生命周期
onMounted(() => {loadGeoJSON();
});
</script><style scoped>
.container {width: 840px;height: 550px;margin: 50px auto;border: 1px solid #42B983;
}#vue-openlayers {width: 800px;height: 420px;margin: 0 auto;border: 1px solid #42B983;position: relative;
}
</style>

四、关键点解析

1. 为什么要用属性哈希来映射颜色?

如果直接在样式函数里 Math.random() 生成颜色,每次渲染(或图层刷新、要素重绘)颜色都会改变,用户体验差。哈希算法可以把同一字符串(比如省名)稳定映射到同一颜色索引,从而保证一致性。

2. 为什么要做样式缓存(styleCache)?

OpenLayers 的样式对象(Style / Fill / Stroke)比较重,每次返回新对象会造成渲染性能问题。将每个颜色对应的 Style 缓存并复用可以显著提升性能。

3. GeoJSON 属性名问题

不同数据来源 properties 的字段名不一致(name / NAME / province / 省名 等)。最好在调试时检查数据,例如:

const features = new GeoJSON().readFeatures(chinaData); console.log(features[0].getProperties());

以确认你要使用的字段名。

4. 使用 import vs fetch

  • import chinaData from '@/assets/map/china.json':将 GeoJSON 打包到 bundle 中,构建时被处理。路径要根据项目别名设置调整。

  • fetch('/map/china.json'):把文件放 public,运行时按路径读取(不会被打包)。适合大文件或运行时更新的 GeoJSON。


五、常见问题 & 解决方法

1) 瓦片不显示或跨域(CORS)问题

  • 使用 HTTPS 的瓦片源(如 https://{a-c}.tile.openstreetmap.org/...),避免混合内容报错。

  • 若使用自己的瓦片服务,需后端配置 CORS。

2) @ 别名找不到

  • Vite 默认并不自动创建 @,但 Vue 官方模板通常配置了。若出错,使用相对路径 import chinaData from '../assets/map/china.json'

3) GeoJSON 地理坐标系不对

  • 本文示例假设 GeoJSON 使用 EPSG:4326(经纬度)。readFeatures 里正确设置 dataProjectionfeatureProjection 很重要,否则要素会显示在错误位置或看不见。

4) 要素样式在缩放下看起来“像素化”或边界线粗细不合适

  • 可以在 style 函数里使用 resolution 参数动态调整边界线宽度,或在高缩放级别改变样式。


六、进阶扩展

  1. 添加鼠标悬停 tooltip —— 使用 Overlay 或监听 pointermove 事件,显示要素名称或统计信息。

  2. 图例(Legend)生成 —— 根据 styleCache 或 colors 映射生成页面图例(缩略色块 + 名称)。

  3. 按属性着色(例如按人口、密度做渐变) —— 使用 d3.scaleSequentiald3.scaleLinear 映射数值到颜色。

  4. 按分组着色 —— 先对要素分组,给不同组分配颜色数组段,或用颜色渐变区分数值区间。

  5. 性能优化 —— 要素非常多(数万)时,考虑简化要素几何(TopoJSON、 simplify)、使用矢量瓦片或按需加载。


文章转载自:

http://uSCXdLKr.srgwr.cn
http://L0dX8zvY.srgwr.cn
http://PSGmmkg3.srgwr.cn
http://Q6h1uBd4.srgwr.cn
http://cZBeVH3l.srgwr.cn
http://TZyg7GjN.srgwr.cn
http://dIJyb1jI.srgwr.cn
http://brebQsAW.srgwr.cn
http://hNvk9XKb.srgwr.cn
http://AqgjOkvv.srgwr.cn
http://m5nidlYE.srgwr.cn
http://WFJWXtX6.srgwr.cn
http://kVYnv3HY.srgwr.cn
http://9iQGQtu3.srgwr.cn
http://xM94kJod.srgwr.cn
http://dRNzQII1.srgwr.cn
http://vBXwLljz.srgwr.cn
http://t09281to.srgwr.cn
http://f9KpyLE2.srgwr.cn
http://SsV6oWG4.srgwr.cn
http://FyAongih.srgwr.cn
http://5ixVOuqI.srgwr.cn
http://lmYMmiHw.srgwr.cn
http://FSItpZFV.srgwr.cn
http://g49T0cyW.srgwr.cn
http://RT9J20jM.srgwr.cn
http://sZ9SfpMm.srgwr.cn
http://6XF0d53q.srgwr.cn
http://YerKKm2m.srgwr.cn
http://QGxYowMx.srgwr.cn
http://www.dtcms.com/a/374377.html

相关文章:

  • 【C++】递归与迭代:两种编程范式的对比与实践
  • 【Java】设计模式——单例、工厂、代理模式
  • C++ ——一文读懂:Valgrind 检测内存泄漏
  • 代码随想录算法训练营第三十一天 | 合并区间、单调递增的数字
  • Redis核心通用命令深度解析:结合C++ redis-plus-plus 实战指南
  • 三防手机的三防是指什么?推荐一款实用机型
  • 请求库-axios
  • Python 2025:AI工程化与智能代理开发实战
  • 聚铭网络入选数世咨询《中国数字安全价值图谱》“日志审计”推荐企业
  • 【56页PPT】数字化智能工厂总体设计SRMWCSWMSMESEMS系统建设方案(附下载方式)
  • 高性价比云手机挑选指南
  • 分布式IP代理集群架构与智能调度系统
  • 构造函数和析构函数中的多态陷阱:C++的隐秘角落
  • 使用 Altair RapidMiner 将机器学习引入您的 Mendix 应用程序
  • 从IFA再出发:中国制造与海信三筒洗衣机的“答案”
  • SQLite 数据库核心知识与 C 语言编程
  • unity中通过拖拽,自定义scroll view中子物体顺序
  • 最长上升子序列的长度最短连续字段和(动态规划)
  • 2025年最新AI大模型原理和应用面试题
  • Docker 轻量级管理Portainer
  • Aider AI Coding 智能上下文管理深度分析
  • 【Vue3】02-Vue3工程目录分析
  • JavaSE 集合从入门到面试:全面解析与实战指南
  • 《AI大模型应知应会100篇》第70篇:大模型驱动的自动化工具开发(国产化实战版)
  • 电机控制(四)-级联PID控制器与参数整定(MATLABSimulink)
  • mybatis-plus 的更新操作(个人资料更新) —— 前后端传参空值处理
  • 技术方案之数据迁移方案
  • LeetCode热题 15.三数之和(双指针)
  • 我对 OTA 的理解随记,附GD32/STM32例程
  • 快速构建数据集-假数据(生成划分)