OpenLayers 图层加载进度条

89 阅读4分钟

前言

图层加载具有生命周期,什么时候开始加载?什么时候正在加载?什么时候加载完成?在图层加载过程中,经常需要判别图层是否加载完成。在OpenLayers如何查看图层加载进度呢?

1. 基本原理

要实现显示图层加载进度可以通过监听图层数据源事件来完成,像矢量数据源具有[featuresloadstart](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.VectorSourceEvent.html#event:featuresloadstart)[featuresload](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.VectorSourceEvent.html#event:featuresloadstart)end两个事件进行处理。[featuresloadstart](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.VectorSourceEvent.html#event:featuresloadstart)事件对应要素开始加载阶段,[featuresload](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.VectorSourceEvent.html#event:featuresloadstart)end事件对应要素加载结束事件。并在事件监听过程中修改计数器的值。

2. 创建进度条构造函数

进度条构造函数初始参数为targetEle, countEle,分别是进度条目标要素与计数器要素。在进度条原型上添加更新进度条和计数器方法和显示、隐藏进度条的方法。

/**
 * 控制进度条构造函数
 * @targetEle:进度条要素
 * @countEle:计数器要素
 */ 
function Progress(targetEle, countEle) {
    this.el = targetEle
    // 加载总数
    this.loading = 0
    // 已加载数
    this.loaded = 0
    this.countEle = countEle
}

// 更新进度条
Progress.prototype.addLoading = function () {
    ++this.loading
    this.update()
}

// 更新加载数量和计数器
Progress.prototype.addLoaded = function () {
    ++this.loaded
    ++this.countEle.textContent
    this.update()
}

// 更新进度条
Progress.prototype.update = function () {
    const width = ((this.loaded / this.loading) * 100).toFixed(1) + "%"
    this.countEle.textContent = width
    this.el.style.width = width
}

// 显示进度条
Progress.prototype.show = function () {
    this.el.style.visibility = 'visible'
}
// 隐藏进度条
Progress.prototype.hide = function () {
    const style = this.el.style
    // 延迟隐藏
    setTimeout(function () {
        style.visibility = 'hidden'
        style.width = 0
    },250)
}

3. 监听数据源加载

featuresloadstart要素开始加载事件中更新进度条,在featuresloadend要素结束加载事件中更新进度条和计数器。

vectorSource.on("featuresloadstart"function () {
    progress.addLoading()
})
vectorSource.on("featuresloadend"function () {
    progress.addLoaded()
})

4. 监听地图事件

在地图开始加载loadstart事件中显示进度条,在地图加载结束loadend事件中隐藏进度条。

map.on('loadstart'function () {
    progress.show()
})

map.on('loadend'function () {
    progress.hide()
})

5. 完整代码

其中libs文件夹下的包需要更换为自己下载的本地包或者引用在线资源。

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>OpenLayers 图层加载进度条</title>
    <meta charset="utf-8" />

    <link rel="stylesheet" href="../../libs/css/ol9.2.4.css">
    <link rel="stylesheet" href="../../libs/layui/css/layui.css">

    <script src="../../js/config.js"></script>
    <script src="../../libs/js/ol9.2.4.js"></script>
    <script src="../../libs/layui/layui.js"></script>
    <style>
        * {
            padding0;
            margin0;
            font-size14px;
            font-family'微软雅黑';
        }

        html,
        body {
            width100%;
            height100%;
        }

        #map {
            position: absolute;
            top50px;
            bottom0;
            width100%;
            background#E0ECED;
        }

        #top-content {
            position: absolute;
            width100%;
            height50px;
            line-height50px;
            backgroundlinear-gradient(135deg#ff00cc#ffcc00#00ffcc#ff0066);
            color#fff;
            text-align: center;
            font-size32px;
        }

        #top-content span {
            font-size32px;
        }

        .load-count {
            position: absolute;
            top50%;
            left50%;
            transformtranslate(-50%, -50%);
            width100px;
            height100px;
            border-radius50%;
            background-color#00ffcc;
            color#fff;
            text-align: center;
            line-height100px;
        }

        .progress-bar {
            position: absolute;
            bottom0;
            left0;
            height2px;
            backgroundrgba(33150);
            width0;
            transition: width 250ms;
        }
    </style>
</head>

<body>
    <div id="top-content">
        <span>OpenLayers 图层加载进度条</span>
    </div>

    <div id="map"></div>
    <div class="load-count">0</div>
    <div class="progress-bar"></div>

</body>

</html>

<script>

    /**
     * 控制进度条构造函数
     * @targetEle:进度条要素
     * @countEle:计数器要素
     */
    function Progress(targetEle, countEle) {
        this.el = targetEle
        // 加载总数
        this.loading = 0
        // 已加载数
        this.loaded = 0
        this.countEle = countEle
    }

    // 更新进度条
    Progress.prototype.addLoading = function () {
        ++this.loading
        this.update()
    }

    // 更新加载数量和计数器
    Progress.prototype.addLoaded = function () {
        ++this.loaded
        ++this.countEle.textContent
        this.update()
    }
    // 更新进度条
    Progress.prototype.update = function () {
        const width = ((this.loaded / this.loading) * 100).toFixed(1) + "%"
        this.countEle.textContent = width
        this.el.style.width = width
    }

    // 显示进度条
    Progress.prototype.show = function () {
        this.el.style.visibility = 'visible'
    }
    // 隐藏进度条
    Progress.prototype.hide = function () {
        const style = this.el.style
        // 延迟隐藏
        setTimeout(function () {
            style.visibility = 'hidden'
            style.width = 0
        }, 250)
    }
    //地图投影坐标系
    const projection = ol.proj.get('EPSG:3857');
    //==============================================================================//
    //============================天地图服务参数简单介绍==============================//
    //================================vec:矢量图层==================================//
    //================================img:影像图层==================================//
    //================================cva:注记图层==================================//
    //======================其中:_c表示经纬度投影,_w表示球面墨卡托投影================//
    //==============================================================================//
    const TDTImgLayer = new ol.layer.Tile({
        title"天地图影像图层",
        sourcenew ol.source.XYZ({
            url"http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
            attibutions"天地图影像描述",
            crossOrigin"anoymous",
            wrapXfalse
        })
    })
    const TDTImgCvaLayer = new ol.layer.Tile({
        title"天地图影像注记图层",
        sourcenew ol.source.XYZ({
            url"http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
            attibutions"天地图注记描述",
            crossOrigin"anoymous",
            wrapXfalse
        })
    })

    // 文字样式
    const labelStyle = new ol.style.Style({
        textnew ol.style.Text({
            font'12px Calibri,sans-serif',
            overflowtrue,
            // 填充色
            fillnew ol.style.Fill({
                color"#FAFAD2"
            }),
            // 描边色
            strokenew ol.style.Stroke({
                color"#2F4F4F",
                width3,
            }),
        })
    })
    // 行政区样式
    const regionStyle = new ol.style.Style({
        fillnew ol.style.Fill({
            color: [2302302500.25],
        }),
        strokenew ol.style.Stroke({
            color"#00FFFF",
            width1.25,
        }),
    })

    const style = [labelStyle, regionStyle]

    const loadCount = document.querySelector(".load-count")
    const progressBar = document.querySelector(".progress-bar")
    const progress = new Progress(progressBar, loadCount)
    const JSON_URL = "https://geo.datav.aliyun.com/areas_v3/bound/530000_full.json"
    const vectorSource = new ol.source.Vector({
        urlJSON_URL,
        formatnew ol.format.GeoJSON()
    })
    const layer = new ol.layer.Vector({
        source: vectorSource,
        stylefunction (feature) {
            const label = feature.get("name").split(" ").join("n")
            labelStyle.getText().setText(label)
            return style
        },
        decluttertrue
    })

    vectorSource.on("featuresloadstart"function () {
        progress.addLoading()
    })
    vectorSource.on("featuresloadend"function () {
        progress.addLoaded()
    })

    const map = new ol.Map({
        target"map",
        loadTilesWhileInteractingtrue,
        viewnew ol.View({
            center: [101.48510625.008643],
            zoom6.5,
            worldsWrapfalse,
            minZoom1,
            maxZoom20,
            projection'EPSG:4326',
        }),
        layers: [TDTImgLayer, layer],
        // 地图默认控件
        controls: ol.control.defaults.defaults({
            zoomfalse,
            attributiontrue,
            rotatetrue
        })
    })

    map.on('loadstart'function () {
        progress.show()
    })

    map.on('loadend'function () {
        progress.hide()
    })

</script>

OpenLayers示例数据下载,请回复关键字:ol数据

全国信息化工程师-GIS 应用水平考试资料,请回复关键字:GIS考试

【GIS之路】 已经接入了智能助手,欢迎关注,欢迎提问。

欢迎访问我的博客网站-长谈GIShttp://shanhaitalk.com

都看到这了,不要忘记点赞、收藏 + 关注

本号不定时更新有关 GIS开发 相关内容,欢迎关注 !