前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我是如何通过geojson画个中国地图出来的 |Java 开发实战

我是如何通过geojson画个中国地图出来的 |Java 开发实战

原创
作者头像
啵啵肠
发布2023-11-29 11:47:02
3740
发布2023-11-29 11:47:02
举报
文章被收录于专栏:知无不言 - 畅所欲言

GeoJSON是一种对各种地理数据结构进行编码的格式。

前言:前两周我带你们分析了WebGis中关键步骤,下面呢,我带大家来看看Geojson的加载及其点击事件

  • Geojson数据解析

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

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

GeoJSON集合特征:

代码语言:lua
复制
{"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数据。

代码语言:css
复制
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中显示出来,我们还需要指定数据的显示样式,这里和之前瓦片是加载不同,样式很重要我调节了好久才调通的,这里我将封装在方法里。

方法的具体实现:

代码语言:text
复制
	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中绑定事件,也就是注册事件

代码语言:text
复制
map.on('singleclick', mapClick);
代码语言:javascript
复制
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 + "\n这里属于" + featureInfo.feature.get("name") + "点");
		} else if (featureInfo.feature.get("geometry").B.length == 4) {
			alert(hdms + "\n这里属于" + featureInfo.feature.get("name") + "线");
			alert("两端信息" + featureInfo.feature.get("geometry").B);
		} else {
			// alert(hdms+"\n这里属于"+featureInfo.feature.get("name")+"省");//显示点击区域的
		}
		console.log('打印选择要素');
		console.log(featureInfo.feature);
		console.log('打印选择要素所属Layer');
		console.log(featureInfo.layer);
	} else {
		alert(hdms + "\n这里不属于中国或者这里是大海");// 显示点击区域的
	}
}

在这里我需要讲解一下:

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

代码语言:text
复制
var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate,'EPSG:3857', 'EPSG:4326'));

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


  • 定位

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

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

代码语言:ruby
复制
 | 新旧对比 | openlayers2 | openlayers3 |
 |:-------------- |:-------------|:-----|
 | 点击 | 获取经纬度查询 | 点线类别区分 |
 | 定位 | map中心显示 | view中心显示 |

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

代码语言:less
复制
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

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

代码语言:text
复制
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)';
		});
	}
};

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档