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

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">
    
    <link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
    <style>
        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
        .map {
            height: 400px;
            width: 100%;
            float: left;
        }
    style>
    
    <script src="http://openlayers.vip/examples/resources/ol.js">script>
    <script src="./tiandituLayers.js">script>
    <title>OpenLayers exampletitle>
head>
<body>
<h2>Circle Featureh2>

<div id="map" class="map">div>


<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 以单位米为半径,绘制圆形图形要素

Openlayers 教程 - 以单位米为半径,绘制圆形图形要素_第1张图片


参考博客:

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

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

你可能感兴趣的:(Openlayers,学习教程,openlayers创建圆,ol,以米为单位创建圆,openlayers,米创建圆,openlayers,圆形,4326,米半径创建圆)