首页 > 其他分享 >Vue3 + Openlayers10示例 台风轨迹和台风圈

Vue3 + Openlayers10示例 台风轨迹和台风圈

时间:2024-10-15 21:19:44浏览次数:3  
标签:ol 示例 tfPoint let import new 台风 Openlayers10


前言

假装已经完成了vue3和Openlayers10开发环境的搭建,如果有需要,可搜索vue+Openlayers环境搭建的相关文章。

本示例基于Vue3 和 Openlayers10 的环境,实现台风轨迹和台风圈的效果。


一、安装插件

安装Element-plus插件,其实只在台风列表的地方用到了el-checkbox,可根据实际需要取舍。

//安装Element-plus插件
npm install element-plus --save

安装成功后,在vue项目的package.json文件中会有Element-plus插件的依赖,如下图。

二、代码展示

项目中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>
					<Typhoon></Typhoon>
				</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: {
			Typhoon
		},
	}
</script>
<style scoped>
	.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\Typhoon.vue的代码如下:

<template>
    <div class="header">
        <!--利用台风的实况和预报数据,实现台风按轨迹移动的效果-->
        <h2>Vue3 + Openlayers10 实现台风轨迹和风圈效果</h2>
        <el-checkbox :label="item.name" v-for="item in tyhoonList" :value="item.tfid" :key="item.tfid"
            @change="loadTyphoon(item.tfid)">
            {{ item.name }} ( {{item.enname}} : {{item.tfid}} )
        </el-checkbox>
    </div>
    <div id="vue-openlayers"></div>
</template>
<script>
    /* eslint-disable */
    import * as ol from 'ol';
    import { source, layer, vector, geom, style, } from 'ol';

    import VectorSource from 'ol/source/Vector.js';
    import VectorLayer from 'ol/layer/Vector.js';
    import { Style as olStyle, Fill as olFill, Text as olText, Stroke as olStroke, Icon as olIcon } from 'ol/style';

    import * as olProj from 'ol/proj';
    import Feature from 'ol/Feature.js';
    import { LineString, Polygon, Point, Circle } from "ol/geom";

    //导入自定义基础地图
    import BaseMap from './BaseMap.js';

    //本地台风列表数据Json文件
    import tyhoonactivity from "../assets/typhoon/data/tyhoonactivity.json";
    //2024年13号台风贝碧嘉的数据Json文件
    import typhoon_202413 from "../assets/typhoon/data/typhoon_202413_BEBINCA.json";
    //2024年14号台风普拉桑的数据Json文件
    import typhoon_202414 from "../assets/typhoon/data/typhoon_202414_PULASAN.json";
    import imaget01 from "../assets/typhoon/images/t-01.png";
    import imaget02 from "../assets/typhoon/images/t-02.png";
    import imaget03 from "../assets/typhoon/images/t-03.png";
    import imaget04 from "../assets/typhoon/images/t-04.png";
    import imaget05 from "../assets/typhoon/images/t-05.png";
    import imaget06 from "../assets/typhoon/images/t-06.png";


    export default {
        name: 'Typhoon',
        data() {
            return {
                map: null,
                //台风列表
                tyhoonList: null,
                //台风信息详情
                typhoonDetail: null,

                //24小时警戒线
                stromAlertLineLayer24: null,
                //48小时警戒线
                stromAlertLineLayer48: null,

                //台风路径图层
                tfRouteLayer: null,
                //台风圈图层
                tfCircleLayer7: null,
                //台风圈图层
                tfCircleLayer10: null,
                //台风圈图层
                tfCircleLayer12: null,

                //台风路径线样式
                tfLine_olStroke: new olStroke({
                    color: "blue",
                    width: 2,
                }),

                //台风风圈样式
                tfCircleStyles: {
                    //7级
                    tfCircleStyle7: new olStyle({
                        fill: new olFill({
                            color: "rgb(230, 165, 53, 0.2)", // 黄色半透明填充
                        }),
                        stroke: new olStroke({
                            color: "rgb(230, 165, 53)", // 黄色半透明填充
                            width: 1,
                        }),
                        text: new olText({
                            font: "bold 14px 微软雅黑",
                            text: "七级风圈",
                            offsetX: 10,
                            offsetY: 15,
                            fill: new olFill({
                                color: "rgba(230, 165, 53)",
                            }),
                        }),
                    }),

                    //10级
                    tfCircleStyle10: new olStyle({
                        fill: new olFill({
                            color: "rgb(230, 165, 53, 0.5)", // 黄色半透明填充
                        }),
                        stroke: new olStroke({
                            color: "rgb(230, 165, 53)",
                            width: 1,
                        }),
                        text: new olText({
                            font: "bold 14px 微软雅黑",
                            text: "十级风圈",
                            offsetX: 10,
                            offsetY: 15,
                            fill: new olFill({
                                color: "rgb(230, 165, 53)",
                            }),
                        }),
                    }),

                    //12级
                    tfCircleStyle12: new olStyle({
                        fill: new olFill({
                            color: "rgb(230, 165, 53)", // 黄色半透明填充
                        }),
                        stroke: new olStroke({
                            color: "rgb(230, 165, 53)", // 黄色半透明填充
                            width: 1,
                        }),
                        text: new olText({
                            font: "bold 14px 微软雅黑",
                            text: "十二级风圈",
                            offsetX: 10,
                            offsetY: 15,
                            fill: new olFill({
                                color: "rgba(231,45,32,0.16)",
                            }),
                        }),
                    }),
                },
            }
        },
        methods: {
            //初始化地图
            initMap() {
                //创建基础地图
                this.map = new BaseMap({
                    target: "vue-openlayers",
                });
                //绘制台风24、48小时警戒线
                this.DrawStromAlertLineLayer24(true, this.map);
                this.DrawStromAlertLineLayer48(true, this.map);

                //直接用本地样例数据
                this.tyhoonList = tyhoonactivity;

                //初始化台风路径图层
                this.tfRouteLayer = new VectorLayer({
                    source: new VectorSource(),
                    map: this.map,
                    style: this.getTyphoonPointStyleByFeature,
                });

                //初始化风圈图层
                this.tfCircleLayer7 = new VectorLayer({
                    source: new VectorSource(),
                    map: this.map,
                    style: this.tfCircleStyles.tfCircleStyle7,
                });
                this.tfCircleLayer10 = new VectorLayer({
                    source: new VectorSource(),
                    map: this.map,
                    style: this.tfCircleStyles.tfCircleStyle10,
                });
                this.tfCircleLayer12 = new VectorLayer({
                    source: new VectorSource(),
                    map: this.map,
                    style: this.tfCircleStyles.tfCircleStyle12,
                });
            },

            //台风登陆警戒线24、48小时线
            //24 小时警戒线(0°N, 105°E;4.5°N, 113°E;11°N, 119°E;18°N, 119°E;22°N, 127°E;34°N, 127°E)
            //48 小时警戒线(0°N, 105°E; 0°N, 120°E;15°N, 132°E;34°N, 132°E)
            //加载台风24小时警戒线
            DrawStromAlertLineLayer24(visible, map) {
                let alertLine24 = [[127, 34], [127, 22], [119, 18], [113, 4.5], [105, 0]];

                let stromAlertLineLayer24Visible = visible;

                if (stromAlertLineLayer24Visible) {
                    for (var i = 0; i < alertLine24.length; i++) {
                        alertLine24[i] = olProj.transform(alertLine24[i], 'EPSG:4326', 'EPSG:3857');
                    }

                    let featureLine24 = new Feature({
                        name: '24小时警戒线',
                        geometry: new LineString(alertLine24),
                    });

                    let vectorLine24 = new VectorSource({});
                    vectorLine24.addFeature(featureLine24);

                    this.stromAlertLineLayer24 = new VectorLayer({
                        source: vectorLine24,
                        style: new olStyle({
                            fill: new olFill({ color: [237, 41, 51], weight: 4 }),
                            stroke: new olStroke({ color: [237, 41, 51], width: 2 }),
                            text: new olText({
                                font: 'Italic bold 12px 思源黑体',
                                text: '24 小 时 警 戒 线',
                                fill: new olFill({
                                    color: [237, 41, 51],
                                }),
                                placement: 'line',// 标注设置为沿线方向排列
                                textAlign: 'left',
                                textBaseline: 'bottom',
                                rotateWithView: true,
                                rotation: 90,
                            }),
                        }),
                    });

                    if (this.stromAlertLineLayer24 != undefined) {
                        map.removeLayer(this.stromAlertLineLayer24);
                    }
                    map.addLayer(this.stromAlertLineLayer24);
                }
                else {
                    if (this.stromAlertLineLayer24 != undefined) {
                        map.removeLayer(this.stromAlertLineLayer24);
                    }
                }
            },

            //加载台风48小时警戒线
            DrawStromAlertLineLayer48(visible, map) {
                let alertLine48 = [[132, 34], [132, 15], [120, 0], [105, 0]];

                let stromAlertLineLayer48Visible = visible;

                if (stromAlertLineLayer48Visible) {
                    for (var i = 0; i < alertLine48.length; i++) {
                        alertLine48[i] = olProj.transform(alertLine48[i], 'EPSG:4326', 'EPSG:3857');
                    }

                    let featureLine48 = new Feature({
                        name: '48小时警戒线',
                        geometry: new LineString(alertLine48),
                    });

                    let vectorLine48 = new VectorSource({});
                    vectorLine48.addFeature(featureLine48);

                    this.stromAlertLineLayer48 = new VectorLayer({
                        source: vectorLine48,
                        style: new olStyle({
                            fill: new olFill({ color: 'blue', weight: 4 }),
                            stroke: new olStroke({ color: 'blue', width: 2, lineDash: [6, 6] }),
                            text: new olText({
                                font: 'Italic bold 12px 思源黑体',
                                text: '48 小 时 警 戒 线',
                                fill: new olFill({
                                    color: 'blue',
                                }),
                                placement: 'line',// 标注设置为沿线方向排列
                                textAlign: 'left',
                                textBaseline: 'bottom',
                                rotateWithView: true,
                                rotation: 90,
                            }),
                        }),
                    });

                    if (this.stromAlertLineLayer48 != undefined) {
                        map.removeLayer(this.stromAlertLineLayer48);
                    }
                    map.addLayer(this.stromAlertLineLayer48);
                }
                else {
                    if (this.stromAlertLineLayer48 != undefined) {
                        map.removeLayer(this.stromAlertLineLayer48);
                    }
                }
            },

            /***
             * /@description 加载台风
             * /@function
             * /@param ftid 台风ID
             * /@returns 
             ***/
            loadTyphoon(tfid) {
                //直接用本地样例数据
                this.typhoonDetail = (tfid == '202413') ? typhoon_202413 : typhoon_202414;

                let js = JSON.stringify(this.typhoonDetail);
                let jsO = JSON.parse(js);

                //绘制台风
                this.DrawTyphoon(jsO);
            },

            /***
             * @description 刷新绘制台风图层
             * 
             ***/
            DrawTyphoon(tfDetails) {
                //台风路径header信息
                let tfid = tfDetails.tfid,
                    name = tfDetails.name,
                    enname = tfDetails.enname,
                    isactive = tfDetails.isactive,
                    starttime = tfDetails.starttime,
                    endtime = tfDetails.endtime,
                    warnlevel = tfDetails.warnlevel,
                    centerlng = tfDetails.centerlng,
                    centerlat = tfDetails.centerlat;

                let tfPoints = new Array();
                let tfPointsFeature = new Array();
                for (let i = 0; i < tfDetails.points.length; i++) {

                    let tfPoint = tfDetails.points[i];
                    //台风路径点详细信息
                    let time = tfPoint.time,//: 2024-09-10 20:00:00,
                        lng = tfPoint.lng,//: 145.40,   经度
                        lat = tfPoint.lat,//: 12.40,    纬度
                        strong = tfPoint.strong,//: 热带风暴,
                        power = tfPoint.power,//: 8,
                        speed = tfPoint.power,//: 18,
                        pressure = tfPoint.pressure,//: 998,
                        movespeed = tfPoint.pressure,//: 26,
                        movedirection = tfPoint.movedirection,//: 北西,
                        radius7 = tfPoint.radius7,//: 240|220|220|220,
                        radius10 = tfPoint.radius10,
                        radius12 = tfPoint.radius12,
                        forecast = tfPoint.forecast;

                    tfPoints.push(olProj.transform([tfPoint.lng, tfPoint.lat], 'EPSG:4326', 'EPSG:3857'));

                    //将台风路径点详细信息加入台风路径点的集合
                    tfPointsFeature.push(new Feature({
                        id: tfid + "-" + i,
                        geometry: new Point(olProj.transform([tfPoint.lng, tfPoint.lat], 'EPSG:4326', 'EPSG:3857')),
                        name: tfDetails.name,
                        time: tfPoint.time,//: 2024-09-10 20:00:00,
                        lng: tfPoint.lng,//: 145.40,   经度
                        lat: tfPoint.lat,//: 12.40,    纬度
                        strong: tfPoint.strong,//: 热带风暴,
                        power: tfPoint.power,//: 8,
                        speed: tfPoint.power,//: 18,
                        pressure: tfPoint.pressure,//: 998,
                        movespeed: tfPoint.pressure,//: 26,
                        movedirection: tfPoint.movedirection,//: 北西,
                        radius7: tfPoint.radius7,//: 240|220|220|220,
                        radius10: tfPoint.radius10,//: ,
                        radius12: tfPoint.radius12,//: ,
                        forecast: tfPoint.forecast,//:
                    }));
                }

                //将台风路径点加入路径线
                let tfRoute = new LineString(tfPoints);
                //台风路径Feature
                let tfRouteFeature = new Feature({ geometry: tfRoute });

                //台风图层的数据源
                let layerSource_tfRoute = this.tfRouteLayer.getSource();
                layerSource_tfRoute.addFeature(tfRouteFeature);  //添加路径线                
                layerSource_tfRoute.addFeatures(tfPointsFeature);  //添加路径点

                //在台风路径上随便找一个点,画出相应的台风圈
                let lastFeature = tfPointsFeature[tfPointsFeature.length - 42];

                //画台风圈
                TyphoonCircle.Draw(this.tfCircleLayer7, [lastFeature.get('lng'), lastFeature.get("lat")], lastFeature.get("radius7"));
                TyphoonCircle.Draw(this.tfCircleLayer10, [lastFeature.get('lng'), lastFeature.get("lat")], lastFeature.get("radius10"));
                TyphoonCircle.Draw(this.tfCircleLayer12, [lastFeature.get('lng'), lastFeature.get("lat")], lastFeature.get("radius12"));
            },

            //获取台风路径点和路径线的Style样式对象
            getTyphoonPointStyleByFeature(feature) {

                let img = undefined;
                switch (feature.get('strong')) {
                    case "热带低压": img = imaget01;
                        break;
                    case "热带风暴": img = imaget02;
                        break;
                    case "强热带风暴": img = imaget03;
                        break;
                    case "台风": img = imaget04;
                        break;
                    case "强台风": img = imaget05;
                        break;
                    case "超强台风": img = imaget06;
                        break;
                    default:
                        img = imaget01;
                        break;
                }
                return new olStyle({
                    //线
                    stroke: this.tfLine_olStroke,
                    //点
                    image: new olIcon({
                        src: img,
                    }),
                });
            },
        },
        mounted() {
            this.initMap();
        },
    }


    /***
     * @classdesc 台风圈类
     ***/
    class TyphoonCircle {
        /***
         * @description 构造函数
         * @param {*} vectorLayer 扇形所在图层
         * @param {*} center 扇形圆心点的经纬度坐标(EPSG:4326)
         * @param {*} radius 风圈半径 ("radius7": "220|260|180|260", 风圈格式:东北|东南|西北|西南,具体值为风圈半径,单位:公里。)
         ***/
        constructor(vectorLayer, center, radius) {
            this.layer = vectorLayer;
            this.center = olProj.fromLonLat(center); //将经纬度转换为平面投影坐标
            this.radius = radius;
        }

        /***
         * @description 获取台风圈配置信息的对象
         * @param {*} center 台风圈圆心的经纬度坐标(EPSG:4326)
         * @param {*} radius 台风圈半径("radius7": "220|260|180|260", 风圈格式:东北|东南|西北|西南,具体值为风圈半径,单位:公里。)
         **/
        static getTyphoonCircleConfig(center, radius) {
            //拆分风圈四个象限的半径
            let radiuses = radius.split("|");
            if (radiuses != undefined && radiuses.length == 4) {
                let config = {
                    x: center[0], //台风圈中心点经度
                    y: center[1], //台风圈中心点维度
                    //扇形风场
                    sector: {
                        EN: { r: radiuses[0], startAngle: 0, endAngle: 90 },    //第一象限
                        WN: { r: radiuses[2], startAngle: 90, endAngle: 180 },  //第二象限
                        WS: { r: radiuses[3], startAngle: 180, endAngle: 270 }, //第三象限
                        ES: { r: radiuses[1], startAngle: 270, endAngle: 360 }, //第四象限
                    },
                }
                return config;
            }
        }

        /***
         * @description 绘制方法
         * @param {*} vectorLayer 台风圈所在图层
         * @param {*} center 台风圈圆心的经纬度坐标(EPSG:4326)
         * @param {*} radius 风圈半径 ("radius7": "220|260|180|260", 风圈格式:东北|东南|西北|西南,具体值为风圈半径,单位:公里。)
         ***/
        static Draw(vectorLayer, center, radius) {
            //获取台风圈的配置信息
            let config = TyphoonCircle.getTyphoonCircleConfig(center, radius);

            if (config != undefined) {
                let sectorEN = new TyphoonSector(center, config.sector.EN.r, config.sector.EN.startAngle, config.sector.EN.endAngle).getFeature();
                let sectorES = new TyphoonSector(center, config.sector.ES.r, config.sector.ES.startAngle, config.sector.ES.endAngle).getFeature();
                let sectorWN = new TyphoonSector(center, config.sector.WN.r, config.sector.WN.startAngle, config.sector.WN.endAngle).getFeature();
                let sectorWS = new TyphoonSector(center, config.sector.WS.r, config.sector.WS.startAngle, config.sector.WS.endAngle).getFeature();

                //将四个象限的台风圈扇形添加到台风图层的数据源里
                const vectorSource = vectorLayer.getSource();
                vectorSource.addFeatures([sectorEN, sectorES, sectorWN, sectorWS]);
            }
        }
    }

    class TyphoonSector {
        /***
         * @description 构造函数
         * @param {*} center 扇形圆心点的经纬度坐标(EPSG:4326)
         * @param {*} radius 扇形半径(单位:公里。)
         * @param {*} startAngle 扇形的起始角度
         * @param {*} endAngle 扇形的截止角度
         * 
         ***/
        constructor(center, radius, startAngle, endAngle) {
            this.id = Math.random().toString(36).substr(2, 9); //生成一个随机字符串作为 id
            this.feature = undefined;
            this.center = olProj.fromLonLat(center); //将经纬度转换为平面投影坐标
            this.radius = radius * 1000;    //将半径从公里转成米
            this.startAngle = startAngle;
            this.endAngle = endAngle;

            //画扇形
            this.draw();
        }

        get angleRange() {
            return Math.abs(this.endAngle - this.startAngle);
        }

        get segments() {
            return Math.max(2, this.angleRange); // 每度角有一个点
        }

        get arcPoints() {
            const points = [];
            for (let i = 0; i <= this.segments; i++) {
                const angle = ((this.endAngle - this.startAngle) * i) / this.segments;
                const point = this.calculatePointOnCircle(this.startAngle + angle);
                points.push(point);
            }
            return [this.center, ...points, this.center];
        }

        // 计算圆上的点
        calculatePointOnCircle(angleInDegrees) {
            let angle = (angleInDegrees * Math.PI) / 180; //转换为弧度
            const x = this.center[0] + this.radius * Math.cos(angle);
            const y = this.center[1] + this.radius * Math.sin(angle);
            return [x, y];
        }

        getFeature() {
            return this.feature;
        }

        angle2Radian(angle) {
            return (angle * Math.PI) / 180;
        }

        //画扇形
        draw() {
            this.startAngle = this.startAngle;
            this.endAngle = this.endAngle;

            // 创建扇形的边界线
            // 创建一个LineString对象来表示扇形的边界线
            const line = new LineString(this.arcPoints);

            // 使用LineString对象的坐标创建一个Polygon对象来表示扇形区域
            const polygon = new Polygon([line.getCoordinates()]);
            polygon.rotate(this.angle2Radian(0), this.center);

            // 创建一个Feature对象,并将Polygon对象作为几何信息传入
            this.feature = new Feature({ geometry: polygon });
            // 为当前特征设置一个唯一的标识符
            this.feature.setId(this.id);
        }
    }
</script>

<style scoped>
    #vue-openlayers {
        width: auto;
        margin: auto;
        height: 600px;
        border: 2px solid #4845e490;
    }

    .header {
        width: auto;
        margin: auto;
        text-align: center;
        border: 2px solid #4845e490;
    }
</style>

提示:在Typhoon.vue代码里用到的台风列表和台风详情数据文件已上传,可自行下载并放到相应目录,当前示例是放在了assets/typhoon/data/目录下,使用时通过import引入。

//本地台风列表数据Json文件
import tyhoonactivity from "../assets/typhoon/data/tyhoonactivity.json";

//2024年13号台风贝碧嘉的数据Json文件
import typhoon_202413 from "../assets/typhoon/data/typhoon_202413_BEBINCA.json";

//2024年14号台风普拉桑的数据Json文件
import typhoon_202414 from "../assets/typhoon/data/typhoon_202414_PULASAN.json";

提示:本示例中的台风轨迹和台风圈都一次性完全绘制出来的效果,如果想做实时的台风跟踪监控效果,可以考虑动态加载台风数据并绘制最新轨迹、风圈以及预报的效果。


总结

本示例基于 Vue3 和 Openlayers10 开发,相关插件也均采用能够兼容的版本,可根据自身需要适当取舍。

标签:ol,示例,tfPoint,let,import,new,台风,Openlayers10
From: https://blog.csdn.net/xiudouking/article/details/142862708

相关文章

  • 例2.3列表操作示例
    '''首先先定义一个列表,列表是写在[]里,用逗号隔开的,元素是可以改变的列表的截取语法结构是:变量[头下标:尾下标]'''L=['abc',12,3.45,'python',2.789]#输出完整列表print(L)#输出列表的第一个元素print(L[0])#将列表的第一个元素修改为‘a’L[0]='a'#将列表的第2个元素到第3个元素......
  • MinIO部署及示例
    docker部署dockerrun\-p9000:9000\-p9001:9001\-d\--nameminio\-v/Users/ivan/code/black/dockerData/minio:/data\-e"MINIO_ROOT_USER=ROOT"\-e"MINIO_ROOT_PASSWORD=MINIO123"\quay.io/minio/mi......
  • 获取淘宝商品详情API数据:代码示例
    前提条件在开始之前,你需要在开放平台注册账号,并创建一个应用以获取API密钥(AppKey和AppSecret)。此外,你还需要获取访问令牌(AccessToken),这通常需要通过OAuth2.0认证流程来实现。获取key和secretitem_get-获得商品详情taobao.item_get公共参数请求地址: 名称类型必须......
  • 第二百八十节 JPA教程 - JPA 查询Exists示例
    JPA教程-JPA查询Exists示例如果子查询返回任何行,则EXISTS条件返回true。以下代码显示如何在JPQL中使用带有子查询的EXISTS运算符。Listl=em.createQuery("SELECTeFROMProfessoreWHEREEXISTS"+"(SELECTpFROMPhonepWHEREp.employe......
  • Apache Kafka 使用示例
    Kafka快速入门指南微信公众号:阿俊的学习记录空间小红书:ArnoZhangwordpress:arnozhang1994博客园:arnozhangCSDN:ArnoZhang1994第一步:获取Kafka下载2.13-3.8.0版本的Kafka版本并解压:$tar-xzfkafka_2.13-3.8.0.tgz$cdkafka_2.13-3.8.0第二步:启动Kafka环境注意:你的......
  • <<迷雾>> 第11章 全自动加法计算机(6)--一只开关取数 示例电路
    用一只开关依次将数取出info::操作说明刚启动时,t0=1,t1=t2=0,此时只有IAR`=1.按下开关K不要松开,地址寄存器AR收到一个上升沿信号,保存住当前地址,并提供给存储器(注:第一个地址为0,所以电路中暂看不出什么变化)松开开关K,循环移位计数器RR得到......
  • 【vue文件上传+示例代码】【for循环展示el-teble表格】
    <template><el-rowjustify="space-between"><inputtype="file"id="fileInput"/><el-buttontype="success"@click="doSumbitFile">上传</el-button></el-row>&......
  • ab压测的选项、示例和主要关注的指标意义以及ab压测问题Connection reset by peer (10
    一、ab压测的选项、示例和主要关注的指标意义1.ab压测的一些选项-nrequests    全部请求数-cconcurrency 并发数-ttimelimit   最传等待回应时间-ppostfile    POST数据文件-Tcontent-typePOSTContent-type-vverbosity   Howmuchtroubl......
  • 生产者消费者c++ 讲解和代码示例
    生产者-消费者问题的C++讲解和代码示例一、问题描述生产者-消费者问题是经典的多线程同步问题,涉及两个类型的线程:生产者线程:负责生成数据并放入共享缓冲区。消费者线程:负责从共享缓冲区取出数据进行处理。关键挑战在于:同步:确保生产者和消费者在访问共享缓冲区时不发生......
  • C#通用文档API接口集成示例-合同识别-智能文档识别
    在数字化转型的时代,企业面临着海量的文档数据,这些数据的处理不仅影响工作效率,还对企业的业务决策产生重要影响。然而,手工处理和管理这些文档,不仅效率低下,还可能因为人为错误导致数据的丢失或处理延误。面对这种挑战,智能文档识别技术成为解决企业文档管理难题的关键利器。......