OpenLayers 加载动态数据

169 阅读4分钟

前言

最近,在OpenLayers官网看到一个有趣的例子,通过在地图上生成一些随机点,然后利用三角算法使这些点进行周期运动。

1. 生成点样式

在例子中给随机点设置填充和边线样式,同时为了区分顶点和其它随机点的样式,给顶点设置呢内部填充样式和外部填充样式。

// 点样式
const imageStyle new ol.style.Style({
    imagenew ol.style.Circle({
        radius5,
        fillnew ol.style.Fill({
            color'yellow'
        }),
        strokenew ol.style.Stroke({
            width1,
            color'red'
        })
    })
})
// 顶点内部样式
const headInnerImageStyle new ol.style.Style({
    imagenew ol.style.Circle({
        radius2,
        fillnew ol.style.Fill({
            color"blue"
        })
    })
})
// 顶点外部样式
const headOuterImageStyle new ol.style.Style({
    imagenew ol.style.Circle({
        radius5,
        fillnew ol.style.Fill({
            color"black"
        })
    })
})

2. 生成随机点

监听天地图影像图层postrender事件,在其事件对象中获取矢量上下文。其中用到了渲染对象render方法getVectorContext,该方法返回对象为VectorContext类的子类CanvasImmediateRenderer。CanvasImmediateRenderer类实现了将要素和几何对象直接渲染到HTML5 Cavas上下文。该类的实例在库内部创建,并且与图层和地图抛出的渲染事件potscompose(后合成)precompose(预合成)相关联。

const n = 100 // 随机点数量
const omegaTheta = 30000 // 旋转周期,单位ms
const R = 6e6
const r = 2e6
const p = 2e6

TDTImgLayer.on("postrender", event => {
    console.log("event:", event)
    const vectorContext = ol.render.getVectorContext(event)
    let frameState = event.frameState
    const theta = (2 * Math.PI * frameState.time) / omegaTheta
    const coordinates = []
    for (let i = 0; i < n; ++i) {
        // 角度
        const t = theta + (2 * Math.PI * i) / n
        // 生成x,y坐标
        const x = (R + r) * Math.cos(t) + p * Math.cos(((R + r) * t) / r)
        const y = (R + r) * Math.sin(t) + p * Math.sin(((R + r) * t) / r)
        coordinates.push([x, y])
    }
    // 渲染点样式
    vectorContext.setStyle(imageStyle)
    vectorContext.drawGeometry(new ol.geom.MultiPoint(coordinates))
    // 渲染顶点外部样式 
    const headPoint = new ol.geom.Point(coordinates[coordinates.length - 1])
    vectorContext.setStyle(headOuterImageStyle)
    vectorContext.drawGeometry(headPoint)
    // 渲染顶点内部样式 
    vectorContext.setStyle(headInnerImageStyle)
    vectorContext.drawGeometry(headPoint)
    // 渲染图层
    map.render()
})
map.render()

3. 动态效果图

  • 例子原始算法
// 角度
const t = theta + (2 * Math.PI * i) / n
const x = (R + r) * Math.cos(t) + p * Math.cos(((R + r) * t) / r)
const y = (R + r) * Math.sin(t) + p * Math.sin(((R + r) * t) / r)

  • 圆形运动
// 角度
const t = theta + (2 * Math.PI * i) / n
const x = (R + r) * Math.cos(t)
const y = (R + r) * Math.sin(t)

  • 随机运动
// 角度
const t = theta + (2 * Math.PI * i) / n
const x = (R + r) * Math.cos(Math.PI * Math.random() * 100000)
const y = (R + r) * Math.sin(Math.PI * Math.random() * 100000)

  • 线型运动
// 角度
const t = theta + (2 * Math.PI * i) / n
const x = (R + r) * Math.cos(Math.PI / 2)
const y = (R + r) * Math.sin(t)

4. 完整代码

其中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">

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

        html,
        body {
            width100%;
            height100%;
        }

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

        #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;
        }
    </style>
</head>

<body>
    <div id="top-content">
        <span>OpenLayers 加载动态数据</span>
    </div>
    <div id="map" title="地图显示"></div>
</body>

</html>

<script>
    //地图投影坐标系
    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 map = new ol.Map({
        target"map",
        loadTilesWhileInteractingtrue,
        viewnew ol.View({
            // center: [102.845864, 25.421639],
            center: [00],
            zoom2,
            worldsWrapfalse,
            minZoom1,
            maxZoom20,
            // projection: 'EPSG:4326',
        }),
        layers: [TDTImgLayer]
    })

    // 点样式
    const imageStyle = new ol.style.Style({
        imagenew ol.style.Circle({
            radius5,
            fillnew ol.style.Fill({
                color'yellow'
            }),
            strokenew ol.style.Stroke({
                width1,
                color'red'
            })
        })
    })
    // 顶点内部样式
    const headInnerImageStyle = new ol.style.Style({
        imagenew ol.style.Circle({
            radius2,
            fillnew ol.style.Fill({
                color"blue"
            })
        })
    })
    // 顶点外部样式
    const headOuterImageStyle = new ol.style.Style({
        imagenew ol.style.Circle({
            radius5,
            fillnew ol.style.Fill({
                color"black"
            })
        })
    })

    const n = 100 // 随机点数量
    const omegaTheta = 30000 // 旋转周期,单位ms
    const R = 6e6
    const r = 2e6
    const p = 2e6
    TDTImgLayer.on("postrender"event => {
        console.log("event:", event)
        const vectorContext = ol.render.getVectorContext(event)
        let frameState = event.frameState
        const theta = (2 * Math.PI * frameState.time) / omegaTheta
        const coordinates = []
        for (let i = 0; i < n; ++i) {
            // 角度
            const t = theta + (2 * Math.PI * i) / n
            // 生成x,y坐标
            const x = (R + r) * Math.cos(t) + p * Math.cos(((R + r) * t) / r)
            const y = (R + r) * Math.sin(t) + p * Math.sin(((R + r) * t) / r)
            coordinates.push([x, y])
        }
        // 渲染点样式
        vectorContext.setStyle(imageStyle)
        vectorContext.drawGeometry(new ol.geom.MultiPoint(coordinates))
        // 渲染顶点外部样式 
        const headPoint = new ol.geom.Point(coordinates[coordinates.length - 1])
        vectorContext.setStyle(headOuterImageStyle)
        vectorContext.drawGeometry(headPoint)
        // 渲染顶点内部样式 
        vectorContext.setStyle(headInnerImageStyle)
        vectorContext.drawGeometry(headPoint)
        // 渲染图层
        map.render()
    })
    map.render()
</script>

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

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

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

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

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

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