前言
假装已经完成了vue3和Openlayers10开发环境的搭建,如果有需要,可搜索vue+Openlayers环境搭建的相关文章。
本示例基于Vue3 和 Openlayers10 的环境,利用 ol-wind 插件实现风场效果。
一、安装插件
安装ol-wind插件。
//安装ol-wind插件
npm install ol-wind --save
安装成功后,在vue项目的package.json文件中会有ol-wind插件的依赖,如下图。
二、代码展示
项目中main.js的代码:
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
项目中App.vue的代码:
<template>
<HomePage></HomePage>
</template>
<script>
import HomePage from './views/HomePage.vue'
export default {
name: 'App',
components: {
HomePage,
},
}
</script>
项目中.\views\HomePage.vue的代码:
<template>
<div class="common-layout">
<el-container>
<el-aside width="200px">Vue+Openlayers 开发示例目录</el-aside>
<el-container>
<el-main>
<OlWind></OlWind>
</el-main>
<!--<el-footer>@King空 @格子问道</el-footer>-->
</el-container>
</el-container>
</div>
</template>
<script>
/* eslint-disable */
import OlWind from '../components/Ol_Wind.vue'
export default {
name: 'HomePage',
components: {
OlWind
},
}
</script>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
text-align: center;
text-size-adjust: 10px;
}
.el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
}
body>.el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>
提示:为了方便初始化地图对象和底图,我新建了一个继承至Map的BaseMap类,放在.\src\components\BaseMap.js里。
项目中.\src\components\BaseMap.js的代码如下:
/* eslint-disable */
import "ol/ol.css";
import * as olProj from "ol/proj";
import { Map, View } from "ol";
import Tile from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
/**
* @classdesc
* The map is the core component of OpenLayers. For a map to render, a view,
* one or more layers, and a target container are needed:
*
* import Map from 'ol/Map.js';
* import View from 'ol/View.js';
* import TileLayer from 'ol/layer/Tile.js';
* import OSM from 'ol/source/OSM.js';
*
* const map = new Map({
* view: new View({
* center: [0, 0],
* zoom: 1,
* }),
* layers: [
* new TileLayer({
* source: new OSM(),
* }),
* ],
* target: 'map',
* });
*
* The above snippet creates a map using a {@link module:ol/layer/Tile~TileLayer} to
* display {@link module:ol/source/OSM~OSM} OSM data and render it to a DOM
* element with the id `map`.
*
* The constructor places a viewport container (with CSS class name
* `ol-viewport`) in the target element (see `getViewport()`), and then two
* further elements within the viewport: one with CSS class name
* `ol-overlaycontainer-stopevent` for controls and some overlays, and one with
* CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`
* option of {@link module:ol/Overlay~Overlay} for the difference). The map
* itself is placed in a further element within the viewport.
*
* Layers are stored as a {@link module:ol/Collection~Collection} in
* layerGroups. A top-level group is provided by the library. This is what is
* accessed by `getLayerGroup` and `setLayerGroup`. Layers entered in the
* options are added to this group, and `addLayer` and `removeLayer` change the
* layer collection in the group. `getLayers` is a convenience function for
* `getLayerGroup().getLayers()`. Note that {@link module:ol/layer/Group~LayerGroup}
* is a subclass of {@link module:ol/layer/Base~BaseLayer}, so layers entered in the
* options or added with `addLayer` can be groups, which can contain further
* groups, and so on.
*
* @fires import("./MapBrowserEvent.js").MapBrowserEvent
* @fires import("./MapEvent.js").MapEvent
* @fires import("./render/Event.js").default#precompose
* @fires import("./render/Event.js").default#postcompose
* @fires import("./render/Event.js").default#rendercomplete
* @api
*/
class BaseMap extends Map {
/**
* @param {MapOptions} [options] Map options.
*/
constructor(options) {
//console.log("BaseMap 构造函数");
super(options);
//添加基础底图图层
this.addLayer(
new Tile({
source: new XYZ({
//高德地图
url: "https://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
}),
})
);
//设置View
this.setView(
new View({
projection: "EPSG:3857",
center: olProj.transform([110, 30], "EPSG:4326", "EPSG:3857"),
zoom: 3,
})
);
}
}
export default BaseMap;
至此,准备工作已完成,该示例中最主要的风场组件.\src\components\Ol_Wind.vue的代码如下:
<template>
<div class="header">
<h2>利用 ol-wind 实现风场效果</h2>
</div>
<div id="vue-openlayers"></div>
</template>
<script>
/* eslint-disable */
//导入自定义基础地图
import BaseMap from './BaseMap.js';
//导入ol-wind插件
import { WindLayer } from "ol-wind"
//本地风场数据Json文件
import winddata from "../assets/wind.json"
export default {
name: 'Ol-Wind',
data() {
return {
map: null,
windLayer: null,
}
},
methods: {
initMap() {
//创建基础地图
this.map = new BaseMap({
target: "vue-openlayers",
});
//创建风场图层(添加风场数据)
this.windLayer = new WindLayer(winddata, {
windOptions: {
velocityScale: 0.05,
paths: 3200,
// 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: 3,
generateParticleOption: false
},
fieldOptions: {
wrapX: false,
},
});
this.map.addLayer(this.windLayer); //添加风场图层
},
},
mounted() {
this.initMap();
},
}
</script>
<style scoped>
#vue-openlayers {
width: auto;
height: 800px;
margin: auto;
border: 2px solid #4845e490;
}
.header {
width: auto;
border: 2px solid #4845e490;
margin: auto;
text-align: center;
}
</style>
提示:在Ol_Wind.vue代码里用到的风场数据文件已上传,可自行下载并放到相应目录,当前示例是放在了assets目录下,使用时通过import引入。
//本地风场数据Json文件
import winddata from "../assets/wind.json"
提示:ol-wind的WindLayer风场图层支持两种方式设置风场数据
方法1:利用构造函数的第一个参数data传入。
方法2:利用setData方法传入。
ol-wind中设置风场数据的相关源码如下:
//WindLayer类(data:风场Json数据,options:图层参数)
class WindLayer extends layer.Layer {
constructor(data, options) {
const opt = assign({}, _options, options);
super(opt);
this.options = opt;
this.className_ = options.className !== void 0 ? options.className : "wind-layer";
this.pickWindOptions();
if (data) {
this.setData(data, options.fieldOptions);
}
}
/**
* 设置风场图层数据
* set layer data
* @param data 风场数据
* @param options
* @returns {WindLayer}
*/
setData(data, options = {}) {
if (data && data.checkFields && data.checkFields()) {
this.field = data;
} else if (isArray(data)) {
this.field = formatData(data, options);
} else {
console.error("Illegal data");
}
const renderer = this.getRenderer();
if (renderer && this.field) {
renderer.setData(this.field);
}
this.changed();
return this;
}
总结
本示例基于 Vue 3.5.3 和 Openlayers 10.1.0 开发,相关插件也均采用能够兼容的版本,可根据自身需要适当取舍。