Openlayers 教程 - 以单位米为半径,绘制圆形图形要素

news2024/9/28 21:18:50

Openlayers 教程 - 以单位米为半径,绘制圆形图形要素

    • 核心代码
    • 完整代码:
    • 在线示例

在以往的项目维护中,出现一个问题,使用最新高清底图发现,设置地图最大等级(21级)之后,地图虽然可以渲染 21 级图层,但是并没有请求 21 级图层瓦片数据

思考之后,认为是地图等级参数限制,经过调试发现问题所在不仅于此,后来解决问题,这里记录一下。

本文包括问题原因、问题解决核心代码以及在线示例。


核心代码

这里放上控制地图视野(View)、图层(Layer)、资源(Source)对象缩放等级的代码:

其中加载了一个显示瓦片索引的图层,用来查看图层瓦片请求情况:瓦片索引的图层


// 通过获取地图经纬度和米的转换关系,来计算经纬度半径
function createCircle1(radiusTemp){

    // 通过投影获取每个经纬度单位为多少米,也就是一度多少米
    const metersPerUnit = map.getView().getProjection().getMetersPerUnit();

    // 创建圆形对象
    const circleFeature = new ol.Feature({
        geometry: new ol.geom.Circle(center, radiusTemp / metersPerUnit, 'XY'),
    });

    circleFeature.setStyle(getStyle());

    layer.getSource().addFeature(circleFeature);
}

// 通过投影转换的方式,将米半径转为经纬度半径
function createCircle2(radiusTemp){

    const circle = new ol.geom.Circle(center,
        transformProjection([radiusTemp, 0], 'EPSG:3857', 'EPSG:4326')[0]
        -
        transformProjection([0, 0], 'EPSG:3857', 'EPSG:4326')[0],'XY');

    const circleFeature = new ol.Feature({
        geometry: circle,
    });

    circleFeature.setStyle(getStyle('#00ff00',[255, 0, 255, 0.3]));

    layer.getSource().addFeature(circleFeature);
}

// 先创建米的圆,在转为经纬的圆
function createCircle3(radiusTemp){

    // 创建 3857 投影下的圆形对象
    const circleIn3857 = new ol.geom.Circle(
        ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'), radiusTemp,'XY');

    // 将圆形对象转为 4326
    const circle = circleIn3857.transform('EPSG:3857','EPSG:4326');

    const circleFeature = new ol.Feature({
        geometry: circle,
    });

    circleFeature.setStyle(getStyle('#0000ff',[255, 0, 0, 0.3]));

    layer.getSource().addFeature(circleFeature);
}


完整代码:


<html lang="en">
<head>
    <meta charset="utf-8">
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
    <style>
        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
        .map {
            height: 400px;
            width: 100%;
            float: left;
        }
    </style>
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <script src="http://openlayers.vip/examples/resources/ol.js"></script>
    <script src="./tiandituLayers.js"></script>
    <title>OpenLayers example</title>
</head>
<body>
<h2>Circle Feature</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>
<!--注意:本示例将 高德腾讯坐标设置为黑色;将百度坐标设置为黄色 -->
<!--注意:本示例将 高德腾讯坐标转为WGS84颜色设置为粉色;将百度坐标转为WS84颜色设置为绿色 -->
<script type="text/javascript">
    var map = new ol.Map({
        // 地图容器
        target: 'map',
        // 地图图层,比如底图、矢量图等
        layers: [
            getIMG_CLayer(),
            getIBO_CLayer(),
            getCIA_CLayer(),
        ],
        // 地图视野
        view: new ol.View({
            projection: "EPSG:4326",
            // 定位
            center: [116, 39],
            // 缩放
            zoom: 4,
            maxZoom: 18,
            minZoom: 1,
        })
    });

    // 矢量图层
    var layer = initVectorLayer();

    /**
     * @todo 矢量图层
     * @returns {VectorLayer}
     * @constructor
     */
    function initVectorLayer() {
        //实例化一个矢量图层Vector作为绘制层
        let source = new ol.source.Vector();
        //创建一个图层
        let customVectorLayer = new ol.layer.Vector({
            source: source,
            zIndex: 2,
            //设置样式
            style: new ol.style.Style({
                //边框样式
                stroke: new ol.style.Stroke({
                    color: 'red',
                    width: 5,
                    lineDash: [3, 5]
                }),
                //填充样式
                fill: new ol.style.Fill({
                    color: 'rgba(0, 0, 255, 0.3)',
                }),
                image: new ol.style.Circle({
                    radius: 9,
                    fill: new ol.style.Fill({
                        color: 'red',
                    })
                })
            }),
        });
        //将绘制层添加到地图容器中
        map.addLayer(customVectorLayer);

        return customVectorLayer;
    }

    function transformProjection(arr, EPSG, EPSG2) {
        try {
            if (EPSG2 && EPSG) {
                if (arr && arr.length === 4) {
                    return ol.proj.transformExtent(arr, EPSG, EPSG2);
                } else {
                    return ol.proj.transform(arr, EPSG, EPSG2);
                }
            }
            return undefined;
        } catch (e) {
            console.error(e);
        }
    }

    function getStyle(stroke = '#ff0000',fill = [0, 0, 255, 0.3]){

        return new ol.style.Style({
            //边框样式
            stroke: new ol.style.Stroke({
                color: stroke,
                width: 2,
            }),
            //填充样式
            fill: new ol.style.Fill({
                color: fill,
            })
        })
    }

    function clearLayer(){
        layer && layer.getSource().clear();
    }

    // 半径
    const radius = 10010;
    const center = [121.4659, 31.2];

    // 通过获取地图经纬度和米的转换关系,来计算经纬度半径
    function createCircle1(radiusTemp){

        clearLayer();

        radiusTemp = radiusTemp || radius;

        // 通过投影获取每个经纬度单位为多少米,也就是一度多少米
        const metersPerUnit = map.getView().getProjection().getMetersPerUnit();

        // 创建圆形对象
        const circleFeature = new ol.Feature({
            geometry: new ol.geom.Circle(center, radiusTemp / metersPerUnit, 'XY'),
        });

        circleFeature.setStyle(getStyle());

        layer.getSource().addFeature(circleFeature);

        // 定位
        positionLayer(layer);
    }

    // 通过投影转换的方式,将米半径转为经纬度半径
    function createCircle2(radiusTemp){

        clearLayer();

        radiusTemp = radiusTemp || radius;

        const circle = new ol.geom.Circle(center,
            transformProjection([radiusTemp, 0], 'EPSG:3857', 'EPSG:4326')[0]
            -
            transformProjection([0, 0], 'EPSG:3857', 'EPSG:4326')[0],'XY');

        const circleFeature = new ol.Feature({
            geometry: circle,
        });

        circleFeature.setStyle(getStyle('#00ff00',[255, 0, 255, 0.3]));

        layer.getSource().addFeature(circleFeature);

        // 定位
        positionLayer(layer);
    }

    // 先创建米的圆,在转为经纬的圆
    function createCircle3(radiusTemp){

        clearLayer();

        radiusTemp = radiusTemp || radius;

        // 创建 3857 投影下的圆形对象
        const circleIn3857 = new ol.geom.Circle(
            ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'), radiusTemp,'XY');

        // 将圆形对象转为 4326
        const circle = circleIn3857.transform('EPSG:3857','EPSG:4326');

        const circleFeature = new ol.Feature({
            geometry: circle,
        });

        circleFeature.setStyle(getStyle('#0000ff',[255, 0, 0, 0.3]));

        layer.getSource().addFeature(circleFeature);

        // 定位
        positionLayer(layer);
    }

    // 定位到图层 layer
    function positionLayer() {

        const extent = layer.getSource().getExtent();
        //定位范围
        map.getView().fit(extent, {
            duration: 100,//动画的持续时间,
            callback: function () {
                // alert("positionLayer compete !")
            },
        });
    }

</script>

<button id="createCircle1" onclick="createCircle1()">经纬度转米创建圆</button>
<button id="createCircle2" onclick="createCircle2()">投影距离转换半径创建圆</button>
<button id="createCircle3" onclick="createCircle3()">3857创建圆转经纬度</button>
</body>
</html>



在线示例

在线示例:Openlayers 以单位米为半径,绘制圆形图形要素

在这里插入图片描述


参考博客:

[1]: OpenLayers5在EPSG:4326下以m为单位画圆

[2]: openlayers绘制圆形的几种方式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/906663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Steam搬砖项目:最长久稳定的副业!

项目应该大家都有听说话&#xff0c;但是细节问题&#xff0c;如何操作可能有些不是很清楚&#xff0c;今天在这里简单分享一下。 这个Steam搬砖项目主要赚钱汇率差和价值差&#xff0c;是一个细分领取的小项目。 不用引流&#xff0c;时间也是比较自由的&#xff0c;你可以兼…

vue 可拖拽可缩放 vue-draggable-resizable 组件常用总结

特征 没有依赖 使用可拖动&#xff0c;可调整大小或两者兼备定义用于调整大小的句柄限制大小和移动到父元素或自定义选择器将元素捕捉到自定义网格将拖动限制为垂直或水平轴保持纵横比启用触控功能使用自己的样式为句柄提供自己的样式 安装和基本用法 npm install --save vue-d…

【BASH】回顾与知识点梳理(三十七)

【BASH】回顾与知识点梳理 三十七 三十七. 基础系统设定与备份策略37.1 系统基本设定网络设定 (手动设定与 DHCP 自动取得)手动设定 IP 网络参数(nmcli)自动取得 IP 参数(dhcp)修改主机名(hostnamectl) 37.2 日期与时间设定时区的显示与设定时间的调整用 ntpdate 手动网络校时 …

Istio入门体验系列——基于Istio的灰度发布实践

导言&#xff1a;灰度发布是指在项目迭代的过程中用平滑过渡的方式进行发布。灰度发布可以保证整体系统的稳定性&#xff0c;在初始发布的时候就可以发现、调整问题&#xff0c;以保证其影响度。作为Istio体验系列的第一站&#xff0c;本文基于Istio的流量治理机制&#xff0c;…

MyBatis的基本入门及Idea搭建MyBatis坏境且如何实现简单的增删改查(CRUD)---详细介绍

一&#xff0c;MaBatis是什么&#xff1f; 首先是一个开源的Java持久化框架&#xff0c;它可以帮助开发人员简化数据库访问的过程并提供了一种将SQL语句与Java代码进行解耦的方式&#xff0c;使得开发人员可以更加灵活地进行数据库操作。 1.1 Mabatis 受欢迎的点 MyBatis不仅是…

玄而又玄——我亲历的三大总线

总线是计算机系统中的桥梁和公路。对于要学习计算机系统的人来说&#xff0c;如果不理解总线&#xff0c;那么很多认知就没办法落到实处&#xff0c;想不清两样东西是如何连接起来&#xff0c;数据是如何从一点到另一点的。 最近两三年&#xff0c;做了比较多的底层开发&#x…

Scratch 之 创作小技巧 -- 让触碰效果更丝滑

今天小技巧的主题是——丝滑 a.让触碰效果更丝滑 ——非线性放大 相信大家&#xff0c;做游戏时都会有一开始按键吧&#xff0c;把鼠标放上去&#xff0c;这个按键就会有相应的变化&#xff0c;如放大&#xff0c;作为初学者&#xff0c;这段的代码可能是这样↓ 虽然看起来挺…

解析大规模开发:提升企业级开发效率与质量,加速创新

在数字化转型的大环境下&#xff0c;越来越多的企业依赖软件来驱动业务和创新。然而&#xff0c;随着开发规模日益庞大&#xff0c;如何更好地提升研发效能&#xff0c;从而塑造更强大的竞争力&#xff0c;已然成为众多企业亟待解决的共同难题。 作为国内领先的DevSecOps提供商…

凉而不冷 柔而不弱 三菱重工海尔舒适风科技助您整夜安眠

古人云&#xff1a;安寝乃人生乐事。可随着夏天的到来&#xff0c;昼长夜短&#xff0c;家里的老人、儿童、父母都存在不同的入睡苦恼。对于儿童来说&#xff0c;空调温度调的太低容易踢被子着凉&#xff0c;温度调的高又怕孩子满头大汗&#xff1b;父母自身也会因为半夜帮孩子…

盛元广通高校实验室开放预约与综合管理系统LIMS

系统概述&#xff1a; 高校实验室涉及到的课程、老师、学生多&#xff0c;管理起来费时费力&#xff0c;盛元广通高校实验室开放预约与综合管理系统LIMS提供简单易用的账号管理、实验室管理、课程管理、实验项目管理、实验时间设定&#xff1b;为学生提供简单易用的自主实验选…

使用 NBAR(基于网络的应用程序识别) 进行应用流量分析

识别和分类网络应用程序是有效管理网络带宽的关键。通过对网络流量进行分类&#xff0c;管理员可以根据企业的需要可视化、组织和确定网络流量的优先级。通过识别和分类网络流量&#xff0c;网络管理员可以有效地应用 QoS 策略&#xff0c;从而实现优化的网络带宽性能。 什么是…

docker 安装oracle19c linux命令执行sql

docker安装oracle # 下载镜像 19.3.0.0.0 docker pull registry.cn-hangzhou.aliyuncs.com/laowu/oracle:19c # 创建文件 mkdir -p /home/mymount/oracle19c/oradata # 授权&#xff0c;不授权会导致后面安装失败 chmod 777 /home/mymount/oracle19c/oradatadocker run -d \ …

0基础学习VR全景平台篇 第88篇:智慧眼-成员管理

一、功能说明 成员管理&#xff0c;是指管理智慧眼项目的成员&#xff0c;拥有相关权限的人可以进行添加成员、分配成员角色、设置成员分类、修改成员以及删除成员五项操作。但是仅限于管理自己的下级成员&#xff0c;上级成员无权管理。 二、前台操作页面 登录智慧眼后台操…

JS中如何区分变量是数组还是对象

总结&#xff1a; 这里提供三种方法&#xff1a; var arr[] var arr2{}1、constructor:数组的constructor是function Array(){};对象的constructor是function Object(){}2、instanceof&#xff1a;数组 instanceof Array&#xff1a;为true;对象 instanceof Array: 为false;3、…

ICASSP 2023说话人识别方向论文合集

今年入选 ICASSP 2023 的论文中&#xff0c;说话人识别&#xff08;声纹识别&#xff09;方向约有64篇&#xff0c;初步划分为Speaker Verification&#xff08;31篇&#xff09;、Speaker Recognition&#xff08;9篇&#xff09;、Speaker Diarization&#xff08;17篇&#…

GuLi商城-前端基础Vue指令-单向绑定双向绑定

什么是指令? 指令 (Directives) 是带有 v- 前缀的特殊特性。 指令特性的预期值是:单个 JavaScript 表达式。 指令的职责是&#xff0c;当表达式的值改变时&#xff0c;将其产生的连带影响&#xff0c;响应式地作用于DOM 例如我们在入门案例中的 v-on&#xff0c;代表绑定事…

IO多路复用(poll:与select类似,当监测的文件描述符有一个或多个就绪时,执行对应的IO操作

使用poll实现TCP循环服务器接收客户端消息并打印 服务器 客户端 写一个makefile方便使用 结果 笔记

611. 有效三角形的个数

611. 有效三角形的个数 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 611. 有效三角形的个数 https://leetcode.cn/problems/valid-triangle-number/description/ 完成情况&#xff1a; 解题思路&#xff1a; …

第一篇:编写 Hello World 程序

编写 Hello World 程序 Hello World 程序就是让应用程序显示 Hello World 字符串。这是最简单的应用&#xff0c;但却包含了一个应用程序的基本要素&#xff0c;所以一般使用它来演示程序的创建过程。本章要讲的就是在Qt Creator 中创建一个图形用户界面的项目&#xff0c;从而…

什么是数字化?什么是数字化转型?为什么企业选择数字化转型?

数字化&#xff1a; 数字化是指将模拟信息或物理对象转换为数字格式的过程。这涉及将数据、文档、图像、视频和其他形式的信息转换为可以以电子方式处理、存储和传输的二进制代码。与传统的模拟方法相比&#xff0c;数字化可以更有效地存储、检索和操作数据。 数字化转型&…