1、前言
最近有同志询问如何在OpenLayers
中实现军事箭头的标绘,我在这里做了一个例子,效果如下图所示:
2、实现方法
其实绘制军标并不难,关键是找准坐标点。先来看一张图:
上图中红色的线为连接起点和终点所得,我们需要根据这条线确定序号0-6
的七个点的坐标,排除一些特殊情况,如红线平行于X
轴或Y
轴,想要得到这七个点的坐标并不困难,你可以用一次函数的方法算解析式,也可以用三角函数。我这里采用三角函数计算,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>军标绘制</title>
<link rel="stylesheet" href="libs/ol/ol.css" />
<script src="libs/ol/ol.js"></script>
</head>
<body>
<div id="map"></div>
<script>
// 创建图层
var layer = new ol.layer.Vector({
source: new ol.source.Vector()
});
// 东北
var p1 = getPoints([120.2, 30.2], [120.6, 30.6], 0.08, 0.22, 0.65)
var f1 = new ol.Feature({
geometry: new ol.geom.Polygon([p1])
});
f1.setStyle(getStyle('red'));
layer.getSource().addFeature(f1);
// 西北
var p2 = getPoints([119.8, 30.2], [119.4, 30.6], 0.08, 0.22, 0.65)
var f2 = new ol.Feature({
geometry: new ol.geom.Polygon([p2])
});
f2.setStyle(getStyle('green'));
layer.getSource().addFeature(f2);
// 西南
var p3 = getPoints([119.8, 29.8], [119.4, 29.4], 0.08, 0.22, 0.65)
var f3 = new ol.Feature({
geometry: new ol.geom.Polygon([p3])
});
f3.setStyle(getStyle('blue'));
layer.getSource().addFeature(f3);
// 东南
var p4 = getPoints([120.2, 29.8], [120.6, 29.4], 0.08, 0.22, 0.65)
var f4 = new ol.Feature({
geometry: new ol.geom.Polygon([p4])
});
f4.setStyle(getStyle('yellow'));
layer.getSource().addFeature(f4);
// 正北
var p5 = getPoints([120.0, 30.2], [120.0, 30.7], 0.08, 0.22, 0.65)
var f5 = new ol.Feature({
geometry: new ol.geom.Polygon([p5])
});
f5.setStyle(getStyle('Magenta'));
layer.getSource().addFeature(f5);
// 正南
var p6 = getPoints([120.0, 29.8], [120.0, 29.3], 0.08, 0.22, 0.65)
var f6 = new ol.Feature({
geometry: new ol.geom.Polygon([p6])
});
f6.setStyle(getStyle('Sienna'));
layer.getSource().addFeature(f6);
// 正西
var p7 = getPoints([120.2, 30.0], [120.7, 30.0], 0.08, 0.22, 0.65)
var f7 = new ol.Feature({
geometry: new ol.geom.Polygon([p7])
});
f7.setStyle(getStyle('Indigo'));
layer.getSource().addFeature(f7);
// 正东
var p8 = getPoints([119.8, 30.0], [119.3, 30.0], 0.08, 0.22, 0.65)
var f8 = new ol.Feature({
geometry: new ol.geom.Polygon([p8])
});
f8.setStyle(getStyle('Teal'));
layer.getSource().addFeature(f8);
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120.3, 30.3],
zoom: 10
})
});
// 获取坐标点
function getPoints(start, end, r1, r2, r3) {
var array = [];
var angle = Math.atan(Math.abs(end[1] - start[1]) / Math.abs(end[0] - start[0]));
var split = [start[0] + (end[0] - start[0]) * r3, start[1] + (end[1] - start[1]) * r3];
var length = Math.sqrt(Math.pow(end[1] - start[1], 2) + Math.pow(end[0] - start[0], 2));
var h1 = length * r1;
var h2 = length * r2;
if (start[0] < end[0] && start[1] < end[1]) {
// 东北方向
// 0、6、7
array[0] = [start[0] - h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
array[6] = [start[0] + h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
array[7] = [start[0] - h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
// 1、5
array[1] = [split[0] - h1 * Math.sin(angle), split[1] + h1 * Math.cos(angle)];
array[5] = [split[0] + h1 * Math.sin(angle), split[1] - h1 * Math.cos(angle)];
// 2、4
array[2] = [split[0] - h2 * Math.sin(angle), split[1] + h2 * Math.cos(angle)];
array[4] = [split[0] + h2 * Math.sin(angle), split[1] - h2 * Math.cos(angle)];
// 3
array[3] = [end[0], end[1]];
} else if (start[0] > end[0] && start[1] < end[1]) {
// 西北方向
// 0、6、7
array[0] = [start[0] - h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
array[6] = [start[0] + h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
array[7] = [start[0] - h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
// 1、5
array[1] = [split[0] - h1 * Math.sin(angle), split[1] - h1 * Math.cos(angle)];
array[5] = [split[0] + h1 * Math.sin(angle), split[1] + h1 * Math.cos(angle)];
// 2、4
array[2] = [split[0] - h2 * Math.sin(angle), split[1] - h2 * Math.cos(angle)];
array[4] = [split[0] + h2 * Math.sin(angle), split[1] + h2 * Math.cos(angle)];
// 3
array[3] = [end[0], end[1]];
} else if (start[0] > end[0] && start[1] > end[1]) {
// 西南方向
// 0、6、7
array[0] = [start[0] + h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
array[6] = [start[0] - h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
array[7] = [start[0] + h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
// 1、5
array[1] = [split[0] + h1 * Math.sin(angle), split[1] - h1 * Math.cos(angle)];
array[5] = [split[0] - h1 * Math.sin(angle), split[1] + h1 * Math.cos(angle)];
// 2、4
array[2] = [split[0] + h2 * Math.sin(angle), split[1] - h2 * Math.cos(angle)];
array[4] = [split[0] - h2 * Math.sin(angle), split[1] + h2 * Math.cos(angle)];
// 3
array[3] = [end[0], end[1]];
} else if (start[0] < end[0] && start[1] > end[1]) {
// 东南方向
// 0、6、7
array[0] = [start[0] + h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
array[6] = [start[0] - h1 * Math.sin(angle), start[1] - h1 * Math.cos(angle)];
array[7] = [start[0] + h1 * Math.sin(angle), start[1] + h1 * Math.cos(angle)];
// 1、5
array[1] = [split[0] + h1 * Math.sin(angle), split[1] + h1 * Math.cos(angle)];
array[5] = [split[0] - h1 * Math.sin(angle), split[1] - h1 * Math.cos(angle)];
// 2、4
array[2] = [split[0] + h2 * Math.sin(angle), split[1] + h2 * Math.cos(angle)];
array[4] = [split[0] - h2 * Math.sin(angle), split[1] - h2 * Math.cos(angle)];
// 3
array[3] = [end[0], end[1]];
} else if (start[0] == end[0] && start[1] != end[1]) {
if (start[1] < end[1]) {
// 正北方向
// 0、6、7
array[0] = [start[0] - h1, start[1]];
array[6] = [start[0] + h1, start[1]];
array[7] = [start[0] - h1, start[1]];
// 1、5
array[1] = [split[0] - h1, split[1]];
array[5] = [split[0] + h1, split[1]];
// 2、4
array[2] = [split[0] - h2, split[1]];
array[4] = [split[0] + h2, split[1]];
// 3
array[3] = [end[0], end[1]];
} else {
// 正南方向
// 0、6、7
array[0] = [start[0] + h1, start[1]];
array[6] = [start[0] - h1, start[1]];
array[7] = [start[0] + h1, start[1]];
// 1、5
array[1] = [split[0] + h1, split[1]];
array[5] = [split[0] - h1, split[1]];
// 2、4
array[2] = [split[0] + h2, split[1]];
array[4] = [split[0] - h2, split[1]];
// 3
array[3] = [end[0], end[1]];
}
} else if (start[0] != end[0] && start[1] == end[1]) {
if (start[0] < end[0]) {
// 正东方向
// 0、6、7
array[0] = [start[0], start[1] + h1];
array[6] = [start[0], start[1] - h1];
array[7] = [start[0], start[1] + h1];
// 1、5
array[1] = [split[0], split[1] + h1];
array[5] = [split[0], split[1] - h1];
// 2、4
array[2] = [split[0], split[1] + h2];
array[4] = [split[0], split[1] - h2];
// 3
array[3] = [end[0], end[1]];
} else {
// 正西方向
// 0、6、7
array[0] = [start[0], start[1] - h1];
array[6] = [start[0], start[1] + h1];
array[7] = [start[0], start[1] - h1];
// 1、5
array[1] = [split[0], split[1] - h1];
array[5] = [split[0], split[1] + h1];
// 2、4
array[2] = [split[0], split[1] - h2];
array[4] = [split[0], split[1] + h2];
// 3
array[3] = [end[0], end[1]];
}
} else {
// 起点与终点重合
array = [[], [], [], [], [], [], [], []];
}
return array;
}
// 创建样式
function getStyle(colorName) {
return new ol.style.Style({
fill: new ol.style.Fill({
color: colorName
})
})
}
</script>
</body>
</html>
3、结语:
本文主要介绍了OpenLayers
中军标箭头的绘制方法。其实GIS
开发中的绘制功能可以拓展的地方还是很多的。比如可以在箭头尾部加个点,如下图所示,有兴趣的同志可以自行拓展。