Openlayers3若干问题汇总

标签: Openlayers 分类: Gis 创建时间:2019-09-20 08:31:19 更新时间:2024-11-15 10:49:43

我是一个挺伤感挺悲观的人,时不时的就想起了不好的事情。写这篇文章的时候,让我想起了我在面试的时候,没有答上来的一个问题,“openlayers3 不支持4490坐标系怎么办?”,“我都是用的4326的坐标系。”,“叠加4490图层的时候,两个没有差别吗?” “差别很小,完全可以重叠。再说了,同时两个图都进行了便宜,最后这种偏移不就抵消了吗?”
我自认为我回答的很好,面试官也没有给出具体的答案,其实回来仔细想想,同时咨询了一些大牛,其实这样的回答根本就是错误的。没有4490坐标系,应该自定义坐标系啊,惭愧,真是令人惭愧。

1.自定义坐标系

openlayer3 使用proj4进行自定义坐标系的定义,打开 epsg.io ,在输入框中输入4490。

选择CGC2000坐标系。

在页面的底部,可以查看如何用不同的语言定义4490坐标系,这里选择了Proj4js,可以看到定义方法为:proj4.defs(“EPSG:4490”,”+proj=longlat +ellps=GRS80 +no_defs”)。

这样就定义好了,如何在地图上使用呢,可以参考openlayers的一个示例 ,这里介绍了 EPSG:27700 的定义,在epsg.io中输入27700,查询到的定义方式也是这样的。

在epsg.io上的EPSG:27700的定义:

2.自定义平面直角坐标系

上面的定义坐标系,是定义的地理坐标系,如何定义平面直角坐标系呢?直角坐标系的创建也非常的简单:

1
2
3
4
5
6
var extent = [0, 0, 1024, 968];
var projection = new Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent,
});
参考文章:
1.Static Image 这是一个加载静态图片的例子,其实也就是无坐标系的情况,定义出来的自然就是平面直角坐标系
2.OpenLayers自定义坐标系 在epsg官网查找相关的定义,然后使用proj4.js进行定义,proj4.defs(“EPSG:4512”,”+proj=tmerc +lat_0=0 +lon_0=135 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs”);
3.openlayer在方位坐标系下显示北极地区地图 这个例子,是定义了一个在北极上空看地图的视角
4.openlayers自定义坐标系以及坐标转换 使用ol3和proj4.js实现的,其实和参考文章2是一样的
5.OpenLayers 3 自定义坐标系 公瑾的文章,这个人很厉害,盲目崇拜下吧。介绍了自定义地图的加载。

3.关于点的自定义样式

这个其实我觉得有点莫名奇妙,我使用的是4.6版本的,在绘制点的时候,只要是为图层添加了样式,就总是无法出现点。最后总结出来,原来是点的样式要用image来绘制,而不是fill。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 错误示例,会发现这样是绘制不出来点的
insCoordLayer = new ol.layer.Vector({
source: new ol.source.Vector({wrapX: false}),
style:new ol.style.Style({
fill: new ol.style.Fill({
color: 'red'
}),
stroke:new ol.style.Stroke({
color:"#fff",
width:2
})
}),
zIndex:15
});

//正确示例
insCoordLayer = new ol.layer.Vector({
source: new ol.source.Vector({wrapX: false}),
style:new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
}),
stroke:new ol.style.Stroke({
color:"#fff",
width:2
})
})
}),
zIndex:15
});

最终的结果就是这个样子:

还有一点,就是Feautre里面的是geometry属性而不是geom属性。

4.绘制箭头

5.getPositon无法获取坐标

使用ol6.4.3版本,获取overlay的坐标尽然是undefine

1
2
3
4
overlay.setPosition(coord);

// 输出为undefine
overlay.getPosition(coord);

6.un无法解除事件

这里需要注意的就是,需要是具名函数,并且不能在一个函数内部,也就是不能每次都重写初始化这个函数,换句话来说,其实具名函数,返回的是要一个地址,只有移除相同地址的函数才可以,如果每一次这个具名函数都会初始化,那么就能移除了。

7.常用的空间分析公式

空间分析,其实可以借助于turf.js这个库,但是这个库有一个缺点,就是坐标系只能是地理坐标系,比如是4326坐标系,但是比如我自定义的像素坐标系,可能就不太适合了,比如计算两点之间的距离,计算线上距离起点多长距离的点。

参考文章:
1.常用空间分析函数 这篇文章中的内容很多,好几种公式:点到点的距离、判断两个点集是否相等、点P到直线AB的垂足及最短距离….
2.js求两个线段的交点
3.JavaScript中点到一个直线的最短距离

8.限制只能绘制线段

需求是这样的,限制只能绘制一条线段,也就是点击两个点,就能绘制出来一条线段,而不是绘制的折线或者是多段线。

因为我设置Draw的 finishCondition 不起作用,于是我换了一种方式实现,也就是通过map.click监听,判断绘制了两个点之后,就结束绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 // 绘图操作
let draw = new Draw({
source: this.pipeSource,
type: "LineString",
stopClick:true,
condition:(event)=>{ // 限制只能绘制一段线
if(this.drawPoint.length<2){
this.drawPoint.push(event.coordinate_);
return true;
}else{
draw.finishDrawing(); // 结束绘制
draw.setActive(false);
return false
}
}
});
this.map.addInteraction(draw);

// 绘制完成
draw.on("drawend",e=>{
this.drawPoint=[];
// 开启拖动
this.dragInteration.setActive(true);
// 结束map事件
this.map.un("click",this.mapClick);
});

// 监听鼠标点击事件
this.map.on("click",this.mapClick);


// 具名点击事件,方便事件的移除
// 当点击两个点之后,结束绘制,并设置不可进行绘制
mapClick(){
if(this.drawPoint.length==2){
this.drawInteration.finishDrawing(); // 结束绘制
this.drawInteration.setActive(false);
}
}

9.绘制带箭头的线

【需求分析】
官方有例子就是在绘制直线的时候,在线段的一个端点处进行箭头的绘制,我这里的需求是更近一步,可不可以从线段的中间进行箭头的绘制呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 设置图层并增加样式
let vector = new VectorLayer({
name:"draw_layer",
source: new VectorSource(),
zIndex:12,
style:this.lineStyleFunction,
});
mainmap.addLayer(vector);

// 绘制箭头
lineStyleFunction(feature) {
let that=this;
const geometry = feature.getGeometry();
const styles = [
// linestring
new Style({
stroke: new Stroke({
color: '#ffcc33',
width: 2,
}),
}),
];

geometry.forEachSegment(function (start, end) {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const rotation = Math.atan2(dy, dx);
// 和官方不同的地方就在获取了线段的中心
let center=[(start[0]+end[0])/2,(start[1]+end[1])/2];
// arrows
styles.push(
new Style({
geometry: new Point(center),
image: new Icon({
src: that.baseUrl + '/img/simulation/arrow.png',
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation,
}),
})
);
});
return styles;
}

10.自定义事件

参考文章中写的挺好

1
2
3
4
5
6
7
// 监听事件
feature.on("someevt",function(e){

});

// 触发事件
feature.dispatchEvent({type: 'someevt', event: event});
参考文章:
1.自定义事件及应用 feature.dispatchEvent({type: ‘mousemove’, event: event});
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。