非科班Java出身GISer

非科班Java出身GISer

Openlayers 教程 - feature(图形要素)点击和双击事件

地图中图形要素(Feature)的点击事件非常常用,曾经通过给整个地图绑定点击事件,然后判断图形要素(Feature)的方式实现功能,但是效果不太合适。

这里介绍一下通过地图传递事件的方式,契合面向对象的思想,实现。

本文包括核心代码、完整代码以及在线示例。


核心代码

地图初始化事件,传递给图形要素(Feature)。

在直接给图形要素(Feature)绑定点击和双击事件。


// 注册地图单击和双击事件
function registerMapEvent(){
    map.on('click', function (event) {
        map.forEachFeatureAtPixel(event.pixel, function (feature) {
            // 为点击的 feature 发送自定义的 click 消息
            try {
                feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
            } catch (e) {
                console.error(e);
            }
            feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event });
        });
    });

    map.on('dblclick', function (event) {
        map.forEachFeatureAtPixel(event.pixel, function (feature) {
            // 为点击的 feature 发送自定义的 dblclick 消息
            try {
                feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
            } catch (e) {
                console.error(e);
            }
            feature.dispatchEvent && feature.dispatchEvent({ type: 'dblclick', event });
        });
    });
}


const feature1 = getFeatureByWKT(polygon1);
const feature2 = getFeatureByWKT(polygon2);

// 单击事件对象
const func1 = function (e){
    alert('触发单击事件,当前图形要素位置:' + e.target.get('position'))
    console.log(e.target)
}

// 记录对象,用于清除事件
feature1.set('eventFunction',func1);
feature1.on('click',func1);

// 双击事件对象
const func2 = function (e){
    alert('触发双击事件,当前图形要素位置:' + e.target.get('position'))
    console.log(e.target)
}

// 记录对象,用于清除事件
feature2.set('eventFunction',func2);
feature2.on('dblclick',func2);


完整代码:



<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="./turf.min.js"></script>
    <script src="./tiandituLayers.js"></script>
    <title>OpenLayers example</title>
    <script>
        var _hmt = _hmt || [];
        (function () {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>
</head>
<body>
<h2>OpenLayers feature click and double click</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>
<br/>
<br/>
<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: [115.67724700667199, 37.73879478106912],
            // 缩放
            zoom: 6,
            maxZoom: 18,
            minZoom: 1,
        })
    });

    // 注册地图单击和双击事件
    function registerMapEvent(){
        map.on('click', function (event) {
            map.forEachFeatureAtPixel(event.pixel, function (feature) {
                // 为点击的 feature 发送自定义的 click 消息
                try {
                    feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
                } catch (e) {
                    console.error(e);
                }
                feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event });
            });
        });

        map.on('dblclick', function (event) {
            map.forEachFeatureAtPixel(event.pixel, function (feature) {
                // 为点击的 feature 发送自定义的 dblclick 消息
                try {
                    feature && feature.set('position', map.getCoordinateFromPixel(event.pixel));
                } catch (e) {
                    console.error(e);
                }
                feature.dispatchEvent && feature.dispatchEvent({ type: 'dblclick', event });
            });
        });
    }

    registerMapEvent();

    // 默认样式
    var defaultStyle = new ol.style.Style({
        //边框样式
        stroke: new ol.style.Stroke({
            color: 'red',
            width: 2,
        }),
        //填充样式
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.3)',
        }),
        image: new ol.style.Circle({
            radius: 5,
            fill: new ol.style.Fill({
                color: 'white',
            })
        })
    })
    // 初始化图层
    var layer = initVectorLayer();
    // 点线面数组
    var features = [];

    // 初始默认数据
    let polygon1 = "POLYGON((112.80630306271966 46.27140545436643,116.23403743771966 44.33781170436643,117.81606868771966 40.29484295436643,117.90395931271966 38.36124920436643,117.81606868771966 35.02140545436643,116.14614681271966 32.38468670436643,113.50942806271966 33.26359295436643,111.75161556271966 34.58195232936643,110.60903743771966 35.46085857936643,113.28970150021968 36.03214764186642,111.35610775021968 36.33976482936642,110.91665462521968 36.91105389186642,111.22427181271968 37.52628826686642,112.10317806271968 37.30656170436642,112.41079525021968 37.78996014186642,112.32290462521968 38.36124920436642,111.44399837521968 38.66886639186642,110.52114681271968 39.10831951686642,110.38931087521968 39.81144451686642,111.09243587521968 40.07511639186642,112.19106868771968 40.38273357936642,112.49868587521968 41.04191326686642,111.88345150021968 41.21769451686642,111.26821712521968 40.86613201686642,110.43325618771968 40.91007732936642,110.65298275021968 41.39347576686642,110.47720150021968 42.66788982936642,111.79556087521968 42.75578045436642,110.38931087521968 43.19523357936642,110.56509212521968 44.24992107936642,111.44399837521968 43.76652264186642,111.79556087521968 44.16203045436642,111.09243587521968 44.60148357936642,111.22427181271968 45.30460857936642,112.10317806271968 44.95304607936642,112.67446712521968 45.26066326686642,111.75161556271968 45.78800701686642,111.88345150021968 46.40324139186642,112.14712337521968 47.94132732936642,112.45474056271968 47.15031170436642,113.99282650021968 47.28214764186642,113.28970150021968 46.79874920436642,114.95962337521968 46.71085857936642,112.80630306271966 46.27140545436643))";
    let polygon2 = "POLYGON((123.94676492355833 44.03121337817592,118.40965554855833 38.23043212817592,121.66160867355833 32.82515869067592,129.30809304855833 33.39644775317592,129.92332742355833 39.46090087817592,123.94676492355833 44.03121337817592))";

    addFeatures();

    // 添加点线面
    function addFeatures() {

        // 这里处理一下,可以自由传图形要素 start===================================================
        layer.getSource().clear();

        features = [];

        const feature1 = getFeatureByWKT(polygon1);
        const feature2 = getFeatureByWKT(polygon2);

        // 单击事件对象
        const func1 = function (e){
            alert('触发单击事件,当前图形要素位置:' + e.target.get('position'))
            console.log(e.target)
        }

        // 记录对象,用于清除事件
        feature1.set('eventFunction',func1);
        feature1.on('click',func1);

        // 双击事件对象
        const func2 = function (e){
            alert('触发双击事件,当前图形要素位置:' + e.target.get('position'))
            console.log(e.target)
        }

        // 记录对象,用于清除事件
        feature2.set('eventFunction',func2);
        feature2.on('dblclick',func2);

        features.push(...[feature1,feature2]);

        layer.getSource().addFeatures(features);

        map.getView().fit(layer.getSource().getExtent(), {
            duration: 1,//动画的持续时间,
            callback: null,
        });
    }

    /**
     * @todo 矢量图层
     * @returns {VectorLayer}
     * @constructor
     */
    function initVectorLayer() {
        //实例化一个矢量图层Vector作为绘制层
        let source = new ol.source.Vector();
        //创建一个图层
        let customVectorLayer = new ol.layer.Vector({
            source: source,
            zIndex: 2,
            //设置样式
            style: defaultStyle,
        });
        //将绘制层添加到地图容器中
        map.addLayer(customVectorLayer);

        return customVectorLayer;
    }

    /**
     * @todo wkt格式数据转化成图形对象
     * @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据
     * @param {string|Projection} sourceCode 源投影坐标系
     * @param {string|Projection} targetCode 目标投影坐标系
     * @returns {Feature}
     */
    function getFeatureByWKT(wkt, sourceCode, targetCode) {
        try {
            let view = map.getView();
            if (!wkt) {
                return null;
            }
            let format = new ol.format.WKT();

            let feature;

            feature = format.readFeature(wkt, {
                featureProjection: targetCode || view.getProjection(),
                dataProjection: sourceCode || view.getProjection(),
            });

            return feature;
        } catch (e) {
            console.log(e);
            return null;
        }
    }

    // 清空事件
    function clearFunc() {

        if(Array.isArray(features) && features.length > 0){
            for (let i = 0; i < features.length; i++) {
                const feature = features[i];
                const func = feature.get('eventFunction');
                feature.un('click',func);
                feature.un('dblclick',func);
            }
        }

    }
</script>
<h4>左侧多边形测试单击事件!</h4>
<h4>右侧多边形测试双击事件!</h4>
<button id="clearFunc" onClick="clearFunc()">关闭事件</button>
</body>
</html>





在线示例

在线示例:Openlayers 教程 - feature(图形要素)点击和双击事件

Openlayers 教程 - feature(图形要素)点击和双击事件-LMLPHP


09-09 07:09