Openlayers 4 中的线字符串方向箭头



我正在尝试制作一个LineString,它在每行的末尾都有箭头来显示路线的方向。我使用官方网站上的一个例子:https://openlayers.org/en/latest/examples/line-arrows.html 示例代码通过用户的绘图创建箭头,但我需要给定 LineString 的箭头。 我的代码包含路线结束和结束的图标。 当我使用

'route': new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6, color: [23, 120, 22, 0.6]
})
}),

在样式中,我的代码有效。但是当我从示例中输入 Linestring 的样式时,它给了我一个错误,说"未捕获的类型错误:c.Y 不是一个函数"。

这是我的代码:

var points = [
[76.8412, 43.2245], [76.8405, 43.2210], [76.8479, 43.2200], [76.8512, 43.2220]
];
var route = new ol.geom.LineString(points);
route.transform('EPSG:4326', 'EPSG:3857');
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
var startMarker = new ol.Feature({
type: 'icon-a',
geometry: new ol.geom.Point(ol.proj.fromLonLat(points[0]))
});
var endMarker = new ol.Feature({
type: 'icon-b',
geometry: new ol.geom.Point(ol.proj.fromLonLat(points[points.length - 1]))
});
var styles = {
'route': function(feature) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-a.png'
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
image: new ol.style.Icon({
src: 'https://openlayers.org/en/v4.6.3/examples/data/arrow.png',
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation
})
}));
});
return styles;
},
'icon-a': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-a.png'
})
}),
'icon-b': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-b.png'
})
})
};
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [routeFeature, startMarker, endMarker]
}),
style: function(feature) {
return styles[feature.get('type')];
}
});
var center = ol.proj.fromLonLat([76.8512, 43.2220]);
var map = new ol.Map({
target: document.getElementById('map'),
view: new ol.View({
center: center,
zoom: 15,
minZoom: 2,
maxZoom: 19
}),
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
]
});
#map {
/* just for testing purposes */
width: 100%;
min-width: 100px;
max-width: 500px;
margin-top: 50px;
height: 50px;
}
<link href="https://openlayers.org/en/v4.6.4/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script>
<div id="map"></div>

首先,您可以使用ol-debug.js而不是ol.js,后者是未压缩的,有助于调试。您得到的例外是

类型错误:style.getImage 不是一个函数(第 30443 行)

您收到该错误是因为您的样式对象是混合的:有些样式是函数,有些是纯 Style 对象。

你可能认为OL可以同时处理两者,你通常是对的。但是,您提供了一个函数来vectorLayer,因此 OL 检测到您提供了一个函数并调用它。该函数的返回值应为样式对象。但是对于route,这将返回一个函数!

所以当OL调用时

style: function(feature) {
return styles[feature.get('type')];
}

它获取类型图标a图标 b的样式,但获取路由的函数。 您需要增强样式函数来处理该特殊情况:

style: function(feature) {
const myStyle = stylesMap[feature.get('type')];
if (myStyle instanceof Function) {
return myStyle(feature);
}
return myStyle;
}

PS:对变量使用相同的名称两次(样式)是不好的做法,可能会导致奇怪的错误。

下面是可运行的示例:

var points = [
[76.8412, 43.2245],
[76.8405, 43.2210],
[76.8479, 43.2200],
[76.8512, 43.2220]
];
var route = new ol.geom.LineString(points);
route.transform('EPSG:4326', 'EPSG:3857');
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
var startMarker = new ol.Feature({
type: 'icon-a',
geometry: new ol.geom.Point(ol.proj.fromLonLat(points[0]))
});
var endMarker = new ol.Feature({
type: 'icon-b',
geometry: new ol.geom.Point(ol.proj.fromLonLat(points[points.length - 1]))
});
var stylesMap = {
'route': function(feature) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-a.png'
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
image: new ol.style.Icon({
src: 'https://openlayers.org/en/v4.6.5/examples/data/arrow.png',
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation
})
}));
});
return styles;
},
'icon-a': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-a.png'
})
}),
'icon-b': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'img/icon-b.png'
})
})
};
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [routeFeature, startMarker, endMarker]
}),
style: function(feature) {
const myStyle = stylesMap[feature.get('type')];
if (myStyle instanceof Function) {
return myStyle(feature);
}
return myStyle;
}
});
var center = ol.proj.fromLonLat([76.8512, 43.2220]);
var map = new ol.Map({
target: document.getElementById('map'),
view: new ol.View({
center: center,
zoom: 15,
minZoom: 2,
maxZoom: 19
}),
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
]
});
html,
body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
#map {
/* just for testing purposes */
width: 100%;
height: 100%;
}
<link href="https://openlayers.org/en/v4.6.5/css/ol.css" rel="stylesheet" />
<script src="https://openlayers.org/en/v4.6.5/build/ol-debug.js"></script>
<div id="map"></div>

最新更新