ol-wind 使用
插件地址:npm ol-wind
教程API地址:ol-wind 教程,不仅只支持ol,几乎所有的主流地图库都支持
bash
# 安装依赖
npm install ol-wind --save
展开代码
vue
<template>
<div class="wind-map-container">
<div ref="mapRef" class="map">
<div class="controls">
<button @click="toggleWindLayer" class="control-btn">
{{ windLayerVisible ? "隐藏风场" : "显示风场" }}
</button>
<div class="slider-control">
<label for="windSpeed">风速: {{ windSpeed }}m/s</label>
<input
type="range"
id="windSpeed"
min="1"
max="20"
v-model="windSpeed"
@input="updateWindSpeed"
/>
</div>
<div class="slider-control">
<label for="particleCount">粒子数量: {{ particleCount }}</label>
<input
type="range"
id="particleCount"
min="500"
max="5000"
step="500"
v-model="particleCount"
@input="updateParticleCount"
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import Map from "ol/Map.js";
import View from "ol/View.js";
import TileLayer from "ol/layer/Tile.js";
import XYZ from "ol/source/XYZ.js";
import "ol/ol.css";
// 导入ol-wind库
import { WindLayer } from "ol-wind";
// 地图容器引用
const mapRef = ref(null);
// 地图实例
let map = null;
// 风场图层实例
let windLayer = null;
// 风场数据
let windData = null;
// 响应式状态
const windLayerVisible = ref(true);
const windSpeed = ref(8);
const particleCount = ref(2000);
// 北京中心点坐标
const center = [116.3972, 39.9075];
// 切换风场图层显示/隐藏
const toggleWindLayer = () => {
if (windLayer) {
windLayer.setVisible(!windLayerVisible.value);
windLayerVisible.value = !windLayerVisible.value;
}
};
// 更新风速
const updateWindSpeed = () => {
if (windLayer) {
windLayer.setWindOptions({
speedFactor: windSpeed.value / 10,
});
}
};
// 更新粒子数量
const updateParticleCount = () => {
if (windLayer) {
windLayer.setWindOptions({
particleCount: particleCount.value,
});
}
};
// 初始化地图
const initMap = () => {
// 创建地图实例
map = new Map({
target: mapRef.value,
layers: [
new TileLayer({
source: new XYZ({
url: "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
}),
],
view: new View({
center: center,
zoom: 5,
projection: "EPSG:4326",
}),
});
};
// 初始化风场图层
const initWindLayer = async () => {
// 生成模拟风场数据
windData = await fetch(
"https://blog.sakitam.com/wind-layer/data/wind.json"
).then((res) => res.json());
// 创建风场图层
windLayer = new WindLayer(windData, {
windOptions: {
// colorScale: scale,
velocityScale: 1 / 20,
paths: 5000,
// eslint-disable-next-line no-unused-vars
colorScale: [
"rgb(36,104, 180)",
"rgb(60,157, 194)",
"rgb(128,205,193 )",
"rgb(151,218,168 )",
"rgb(198,231,181)",
"rgb(238,247,217)",
"rgb(255,238,159)",
"rgb(252,217,125)",
"rgb(255,182,100)",
"rgb(252,150,75)",
"rgb(250,112,52)",
"rgb(245,64,32)",
"rgb(237,45,28)",
"rgb(220,24,32)",
"rgb(180,0,35)",
],
lineWidth: 2,
// colorScale: scale,
generateParticleOption: false,
},
fieldOptions: {
wrapX: true,
// flipY: true,
},
});
// 添加风场图层到地图
map.addLayer(windLayer);
};
onMounted(() => {
// 初始化地图
initMap();
// 初始化风场图层
initWindLayer();
});
onUnmounted(() => {
// 组件卸载时清理
if (map) {
map.setTarget(null);
map = null;
}
windLayer = null;
windData = null;
});
</script>
<style scoped>
.wind-map-container {
position: relative;
width: 100vw;
height: 100vh;
}
.map {
width: 100%;
height: 100%;
}
.controls {
position: absolute;
top: 10px;
right: 10px;
z-index: 1000;
background-color: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 15px;
min-width: 220px;
}
.control-btn {
padding: 8px 12px;
background-color: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.control-btn:hover {
background-color: #359469;
}
.slider-control {
display: flex;
flex-direction: column;
gap: 8px;
}
label {
font-size: 14px;
color: #333;
}
input[type="range"] {
width: 100%;
}
</style>