zoukankan      html  css  js  c++  java
  • 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)

    前言:前两周我带你们分析了WebGis中关键步骤瓦片加载+点击事件(具体的看前两篇文章),下面呢,我带大家来看看Geojson的加载及其点击事件

    • Geojson数据解析

      GeoJSON是一种对各种地理数据结构进行编码的格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。

      一个完整的GeoJSON数据结构总是一个(JSON术语里的)对象。在GeoJSON里,对象由名/值对–也称作成员的集合组成。对每个成员来说,名字总是字符串。成员的值要么是字符串、数字、对象、数组,要么是下面文本常量中的一个:”true”,”false”和”null”。数组是由值是上面所说的元素组成。

      GeoJSON集合特征:

    {"type":"FeatureCollection",
        "features":[
            {"type":"Feature",
             "id":"001",
             "properties":{"name":"新华001"},
             "geometry":{"type": "Point", "coordinates":[121.9850,42.6737]}},
            {"type":"Feature",
             "id":"002",
             "properties":{"name":"新华002"},
             "geometry":{"type": "Point", "coordinates":[121.8345,42.4898]}},
            {"type":"Feature",
             "id":"003",
             "properties":{"name":"峰山1"},
             "geometry":{"type": "LineString", "coordinates":[[121.9850,42.6737],[121.8345,42.4898]]}},
            {"type":"Feature",
             "id":"004",
             "properties":{"name":"新华1001"},
             "geometry":{"type": "Point", "coordinates":[128.9850,42.6737]}},
            {"type":"Feature",
             "id":"005",
             "properties":{"name":"新华1002"},
             "geometry":{"type": "Point", "coordinates":[125.8345,42.4898]}},
            {"type":"Feature",
             "id":"006",
             "properties":{"name":"峰山2"},
             "geometry":{"type": "LineString", "coordinates":[[121.9850,42.6737],[125.8345,42.4898]]}}]}

    • openlayers3代码加载

      至于如何加载地图在第一篇的加载瓦片式地图已经提过了,看完第一篇的你应该知道我是将地图map交接给页面的div中,而map中包含了很多遮罩层,我现在加载GeoJSON就是在最上面的层上在加载url数据。

    var vector = new ol.layer.Vector( {
        source : new ol.source.Vector( {
            // url:
            // 'http://openlayers.org/en/v3.17.1/examples/data/geojson/countries.geojson',
            url : './source/china.json',
            format : new ol.format.GeoJSON()
        }),
        style : selectStyleFunction
    });

    我这是引用本地准备好的数据(可以从服务器上获得,从服务器上只需要将url地址改写成服务地址),加载url完成后并不会在map中显示出来,我们还需要指定数据的显示样式,这里和之前瓦片是加载不同,样式很重要我调节了好久才调通的,这里我将封装在方法里。

    方法的具体实现:

        var style;
        if(feature.getGeometry().getType()=="Point"){
            style = [new ol.style.Style({
                image : new ol.style.Circle( {
                    fill : new ol.style.Fill( {
                        color : 'rgba(255,255,0,0.4)'
                    }),
                    radius : 2,
                    stroke : new ol.style.Stroke( {
                        color : 'black',
                        width : 1
                    })
                 }),
                 text : new ol.style.Text( {
                        fill : textFill,
                        stroke : textStroke,
                        text : view.getZoom()>5?(feature.getId()>2?feature.get("name"):""):""
                    })
                })];
        }else if(feature.getGeometry().getType()=="LineString"){
            if(view.getZoom()<3){
                return ;
            }
            style = [new ol.style.Style( {
                stroke : new ol.style.Stroke( {
                    color : '#CD950C',
                    width : 2
                }),
                 text : new ol.style.Text( {
                        fill : textFill,
                        stroke : textStroke,
                        text : view.getZoom()>6?feature.get("name"):""
                    })
            })];
        }else if(feature.getGeometry().getType()=="Polygon"){
            style = [new ol.style.Style( {
                stroke : new ol.style.Stroke( {
                    color : '#FFE4B5',
                    width : 3
                }),
                 text : new ol.style.Text( {
                        fill : textFill,
                        stroke : textStroke,
                        text : feature.get("name")
                    })
            })];
        }else if(feature.getGeometry().getType()=="MultiLineString"){
            style = [new ol.style.Style( {
                stroke : new ol.style.Stroke( {
                    color : 'black',
                    width : 3
                })
            })];
        }
        return style;
    

    申明 里面有些参数没有进行申明,因为定义了全局变量,因为在之前的js中改的,所以并没贴出所有代码。这里需要完整代码的请CSDN上私信我或者在留言板上留言


    • 效果欣赏

      1、地图加载完毕 这里你看到的地图不是上次的了,这次这个地图就是GeoJSON里的数据,只不过将数据以图形化的形式展现在我们的面前,看到地图右上方的两个点和一条线了吗,那都是通过数据动态加载出来的,换句话来说就是,我只需要将GeoJSON里的数据进行修改一下,这个地图就不一样了,这很方便我们在后台修改地图。还有这个中国的框架也是数据里的,总之一句话你看到的这个地图里所有元素都是数据里设置的(除了样式)

      这里写图片描述

      2、放大缩小地图和之前效果一样,值得注意的是我在js中设置了显示级别,就是放大缩小的不同级别显示的数据也是不同的,比如说那条线吧,我设置在6级以上的才能看到,下面我缩小地图线就不见了,下面是消失了的并不是太小看不见的

      这里写图片描述

      3、在放大到一定级别我设置了点的周围显示点的名称!看效果

      这里写图片描述

      这里就是加载的效果,下面我们继续探讨。下面就是点击事件了,点击事件在上篇文章我是着重讲了原理及实现,而在新技术中我们的点击事件就很Easy了


    • 点击事件

      我们要在map中绑定事件,也就是注册事件

    map.on('singleclick', mapClick);
    function mapClick(e) {
        var pixel = map.getEventPixel(e.originalEvent);
        var featureInfo = map.forEachFeatureAtPixel(pixel,
                function(feature, layer) {
                    return {
                        feature : feature,
                        layer : layer
                    };
                });
        var coordinate = e.coordinate;
        var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate,
                'EPSG:3857', 'EPSG:4326'));
        if (featureInfo !== undefined && featureInfo !== null
                && featureInfo.layer !== null) {
            if (featureInfo.feature.get("geometry").B.length == 2) {
    //          alert(view.getZoom());
                alert(hdms + "
    这里属于" + featureInfo.feature.get("name") + "点");
            } else if (featureInfo.feature.get("geometry").B.length == 4) {
                alert(hdms + "
    这里属于" + featureInfo.feature.get("name") + "线");
                alert("两端信息" + featureInfo.feature.get("geometry").B);
            } else {
                // alert(hdms+"
    这里属于"+featureInfo.feature.get("name")+"省");//显示点击区域的
            }
            console.log('打印选择要素');
            console.log(featureInfo.feature);
            console.log('打印选择要素所属Layer');
            console.log(featureInfo.layer);
        } else {
            alert(hdms + "
    这里不属于中国或者这里是大海");// 显示点击区域的
        }
    }

    在这里我需要讲解一下:

    这里的featureInfo是我们在方法里拼接的(feature+layer)组成的,在if条件判断里我们featureInfo.feature.get(“geometry”).B.length == 2是判断feature里数字点的个数,大家想一想如果是点是不是有两个数字点,如果是线就是两个点也就是四个数字点,如果是区域的话那就是至少是超过4的偶数了,这样我们就可以区别出点线和区域了,这也就是说我们在这里就实现了之前很难解决的点线问题了,区域问题我们就不多加讨论了。

    var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate,'EPSG:3857', 'EPSG:4326'));

    这个是将坐标进行转换的,这个不多说


    • 定位

      在之前我们的定位就是以某个点中心显示并加上图标那就是所谓的定位,那么在我们的新技术中定位是不是有所改变呢?让我们来一探究竟。

      如果你认为既然是新技术了就一定要有突破,那么我的回答可能会让你很失望,新技术里仍然是用上述的思想来实现定位的,但多多少少还是有不同的。

      新旧对比 openlayers2 openlayers3
      点击 获取经纬度查询 点线类别区分
      定位 map中心显示 view中心显示

      由上图的表格我们可以看出我们的定位还是有所区别的,在新技术中我么能采用的是view中心显示法,什么叫view中心显示法呢,就是通过view来调用设置中心的方法。

    view.setCenter(ol.proj.fromLonLat( [
    
    Number(document.getElementById('jd').value),
    
    Number(document.getElementById('wd').value) ]));

    • 其他常用的事件介绍

    事件句柄

    HTML 4.0 的新特性之一是有能力使 HTML 事件触发浏览器中的动作(action),比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,这些属性可插入 HTML 标签来定义事件动作。

    具体事件

    属性 当以下情况发生时,出现此事件 FF N IE
    onabort 图像加载被中断 1 3 4
    onblur 元素失去焦点 1 2 3
    onchange 用户改变域的内容 1 2 3
    onclick 鼠标点击某个对象 1 2 3
    ondblclick 鼠标双击某个对象 1 4 4
    onerror 当加载文档或图像时发生某个错误 1 3 4
    onfocus 元素获得焦点 1 2 3
    onkeydown 某个键盘的键被按下 1 4 3
    onkeypress 某个键盘的键被按下或按住 1 4 3

    此处参考的w3School

    在我的地图中我就随便加了几个试试效果的。

    var select = null; // ref to currently selected interaction
    // select interaction working on "singleclick"
    var selectSingleClick = new ol.interaction.Select();
    
    // select interaction working on "click"
    var selectClick = new ol.interaction.Select( {
        condition : ol.events.condition.click
    });
    
    // select interaction working on "pointermove"
    var selectPointerMove = new ol.interaction.Select( {
        condition : ol.events.condition.pointerMove
    });
    
    var selectAltClick = new ol.interaction.Select( {
        condition : function(mapBrowserEvent) {
            return ol.events.condition.click(mapBrowserEvent)
                    && ol.events.condition.altKeyOnly(mapBrowserEvent);
        }
    });
    
    var selectElement = document.getElementById('type');
    
    var changeInteraction = function() {
        if (select !== null) {
            map.removeInteraction(select);
        }
        var value = selectElement.value;
        if (value == 'singleclick') {
            select = selectSingleClick;
        } else if (value == 'click') {
            select = selectClick;
        } else if (value == 'pointermove') {
            select = selectPointerMove;
        } else if (value == 'altclick') {
            select = selectAltClick;
        } else {
            select = null;
        }
        if (select !== null) {
            map.addInteraction(select);
            select.on('select', function(e) {
                document.getElementById('status').innerHTML = '&nbsp;'
                        + e.target.getFeatures().getLength()
                        + ' selected features (last operation selected '
                        + e.selected.length + ' and deselected '
                        + e.deselected.length + ' features)';
            });
        }
    };

    到这里整个GeoJSON加载地图已经讲解完毕了,上述只是为了帮助各位梳理思路,并不是项目的完整代码,如果新入门的没有看明白,可以在博客下方留言,我会将源码发送给你。

  • 相关阅读:
    单线制DS18B20温度传感器LED数码管显示当前的温度值
    AD转换器的主要指标
    关于swiper动态更改,无法更新的悖论
    在360的兼容模式下关于innerHTML=“”,引发的问题
    比较两个字符串的相似度
    WebSocket使用
    事件绑定addEventListener
    插件开发优缺点
    插件开发宗旨
    学会用博客
  • 原文地址:https://www.cnblogs.com/zhangxinhua/p/8319246.html
Copyright © 2011-2022 走看看