OpenLayers 图层加载进度条

关注我,带你一起学GIS ^

注:当前使用的是 ol [9.2.4] 版本,天地图使用的key请到天地图官网申请,并替换为自己的key

前言

图层加载具有生命周期,什么时候开始加载?什么时候正在加载?什么时候加载完成?在图层加载过程中,经常需要判别图层是否加载完成。在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>
        * {
            padding: 0;
            margin: 0;
            font-size: 14px;
            font-family: '微软雅黑';
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        #map {
            position: absolute;
            top: 50px;
            bottom: 0;
            width: 100%;
            background: #E0ECED;
        }

        #top-content {
            position: absolute;
            width: 100%;
            height: 50px;
            line-height: 50px;
            background: linear-gradient(135deg, #ff00cc, #ffcc00, #00ffcc, #ff0066);
            color: #fff;
            text-align: center;
            font-size: 32px;
        }

        #top-content span {
            font-size: 32px;
        }

        .load-count {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 100px;
            height: 100px;
            border-radius: 50%;
            background-color: #00ffcc;
            color: #fff;
            text-align: center;
            line-height: 100px;
        }

        .progress-bar {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 2px;
            background: rgba(3, 3, 150);
            width: 0;
            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: "天地图影像图层",
        source: new ol.source.XYZ({
            url: "http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
            attibutions: "天地图影像描述",
            crossOrigin: "anoymous",
            wrapX: false
        })
    })
    const TDTImgCvaLayer = new ol.layer.Tile({
        title: "天地图影像注记图层",
        source: new ol.source.XYZ({
            url: "http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
            attibutions: "天地图注记描述",
            crossOrigin: "anoymous",
            wrapX: false
        })
    })

    // 文字样式
    const labelStyle = new ol.style.Style({
        text: new ol.style.Text({
            font: '12px Calibri,sans-serif',
            overflow: true,
            // 填充色
            fill: new ol.style.Fill({
                color: "#FAFAD2"
            }),
            // 描边色
            stroke: new ol.style.Stroke({
                color: "#2F4F4F",
                width: 3,
            }),
        })
    })
    // 行政区样式
    const regionStyle = new ol.style.Style({
        fill: new ol.style.Fill({
            color: [230, 230, 250, 0.25],
        }),
        stroke: new ol.style.Stroke({
            color: "#00FFFF",
            width: 1.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({
        url: JSON_URL,
        format: new ol.format.GeoJSON()
    })
    const layer = new ol.layer.Vector({
        source: vectorSource,
        style: function (feature) {
            const label = feature.get("name").split(" ").join("n")
            labelStyle.getText().setText(label)
            return style
        },
        declutter: true
    })

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

    const map = new ol.Map({
        target: "map",
        loadTilesWhileInteracting: true,
        view: new ol.View({
            center: [101.485106, 25.008643],
            zoom: 6.5,
            worldsWrap: false,
            minZoom: 1,
            maxZoom: 20,
            projection: 'EPSG:4326',
        }),
        layers: [TDTImgLayer, layer],
        // 地图默认控件
        controls: ol.control.defaults.defaults({
            zoom: false,
            attribution: true,
            rotate: true
        })
    })

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

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

</script>

OpenLayers示例数据下载,请在公众号后台回复:ol数据

全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试

GIS之路公众号已经接入了智能助手,欢迎大家前来提问。

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

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

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

 

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部