问题描述
我需要能够在 OpenLayers 5 中绘制多线串(这很容易),并带有可自定义的线端。
例如,如果我正在创建一个标尺工具,我希望多线串的末端是一个“T”,以精确显示线的起点和终点。线条末端的“刻度线”需要是线条几何图形的一部分。
我已经像这样构建了我的生产线...
const draw: olDraw = new olDraw({
source: MapValues.drawSource,type: 'Linestring',style: new olStyle({
fill: new olFill({
color: 'rgba(255,255,0.2)'
}),stroke: new olstroke({
color: '#ffcc33',width: 2
}),image: new CircleStyle({
radius: 7,fill: new olFill({
color: '#ffcc33'
})
})
})
})
draw.on('drawstart',(e: olDrawEvent) => {
const tool = this;
let dStartMeasureTT = this.measuretooltip;
// set sketch
this.sketch = e.feature;
var tooltipCoord = e.coordinate;
tool.listener = this.sketch.getGeometry().on('change',function (evt) {
var geom = evt.target;
var output;
output = tool.formatLength(geom);
tooltipCoord = geom.getLastCoordinate();
tool.measuretooltipElement.innerHTML = output;
tool.measuretooltip.setPosition(tooltipCoord);
});
});
draw.on('drawend',(e: olDrawEvent) => {
const format: olGeoJson = new olGeoJson();
this.shapestring = format.writeGeometry(e.feature.getGeometry(),{ dataProjection: 'epsg:4326',featureProjection: 'epsg:3857',rightHanded: false });
this.featureGeometry = transform(e.feature.getGeometry().getCoordinates(),'epsg:3857','epsg:4326');
// Pull up Create object modal
const initialState = {
message: '',title: 'Ruler Label',iconSize: 'xx-large',iconType: 'error',fontSize: 'x-large',inCharLimit: 50,inObjName: this.measuretooltipElement.innerHTML
};
this.bsModalRef = this.modalService.show(CreateobjectComponent,Object.assign({ class: 'modal-sm
modal-dialog-centered',initialState },this.config));
this.bsModalRef.content.closeBtnName = 'OK';
this.bsModalRef.content.modalProcess.subscribe((objName) => {
if (objName) {
this.saveRulerToDb(objName);
this.createMeasuretooltip();
}
});
});
map.addInteraction(draw);
}
}
解决方法
您可以在 drawend 事件中将绘制的 LineString 几何图形转换为 MultiLineString,然后向其附加开始和结束线。
var raster = new ol.layer.Tile({
source: new ol.source.OSM(),});
var source = new ol.source.Vector();
var vector = new ol.layer.Vector({
source: source,});
var map = new ol.Map({
layers: [raster,vector],target: 'map',view: new ol.View({
center: [-11000000,4600000],zoom: 4,}),});
var draw = new ol.interaction.Draw({
source: source,type: 'LineString',});
draw.on('drawend',function(e) {
var lineString = e.feature.getGeometry();
var multiLineString = new ol.geom.MultiLineString([]);
multiLineString.appendLineString(lineString);
var size = lineString.getLength() / 20; // or use a fixed size if you prefer
var coords = lineString.getCoordinates();
// start
var dx = coords[1][0] - coords[0][0];
var dy = coords[1][1] - coords[0][1];
var rotation = Math.atan2(dy,dx);
var startLine = new ol.geom.LineString([
[coords[0][0],coords[0][1] - size],[coords[0][0],coords[0][1] + size]
]);
startLine.rotate(rotation,coords[0]);
// end
var lastIndex = coords.length - 1;
var dx = coords[lastIndex - 1][0] - coords[lastIndex][0];
var dy = coords[lastIndex - 1][1] - coords[lastIndex][1];
var rotation = Math.atan2(dy,dx);
var endLine = new ol.geom.LineString([
[coords[lastIndex][0],coords[lastIndex][1] - size],[coords[lastIndex][0],coords[lastIndex][1] + size]
]);
endLine.rotate(rotation,coords[lastIndex]);
multiLineString.appendLineString(startLine);
multiLineString.appendLineString(endLine);
e.feature.setGeometry(multiLineString);
});
map.addInteraction(draw);
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
.map {
width: 100%;
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<!--
from How to set different colors for a lineString OpenLayers 5
https://stackoverflow.com/questions/66351764/how-to-set-different-colors-for-a-linestring-openlayers-5
https://codesandbox.io/s/gpx-forked-6wpdy
-->
<meta charset="UTF-8">
<title>LineString T-ends</title>
<!-- Pointer events polyfill for old browsers,see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep"></script>
</head>
<body>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
<link rel="stylesheet" href="https://openlayers.org/en/v6.5.0/css/ol.css" type="text/css">
<div id="map" class="map"></div>
</body>
</html>
- 制作一个图标,作为行尾的横杆:
- 将其添加到 LineStrings 的末尾:
var styleFunction = function (feature) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'blue',// '#ffcc33',width: 2,}) ];
var coords = geometry.getCoordinates();
// start
var dx = coords[1][0] - coords[0][0];
var dy = coords[1][1] - coords[0][1];
var rotation = Math.atan2(dy,dx);
// start crossbar
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point(coords[0]),image: new ol.style.Icon({
// url encoded svg icon to prevent cross-domain issues
src: "data:image/svg+xml;utf8,%3Csvg width='30' height='40' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M 10 10 h 1 v 20 h -1 Z' fill='black' stroke='black'/%3E%3C/svg%3E",anchor: [10,0.5],anchorXUnits: 'pixels',rotateWithView: true,rotation: -rotation,})
);
// end
var lastIndex = coords.length-1;
var dx = coords[lastIndex-1][0] - coords[lastIndex][0];
var dy = coords[lastIndex-1][1] - coords[lastIndex][1];
var rotation = Math.atan2(dy,dx);
// end crossbar
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point(coords[lastIndex]),anchor: [9.5,})
);
return styles;
};
代码片段:
var raster = new ol.layer.Tile({ // TileLayer({
source: new ol.source.OSM(),});
var source = new ol.source.Vector(); // VectorSource();
var styleFunction = function(feature) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'blue',})
];
var coords = geometry.getCoordinates();
// start
var dx = coords[1][0] - coords[0][0];
var dy = coords[1][1] - coords[0][1];
var rotation = Math.atan2(dy,dx);
// start crossbar
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point(coords[0]),image: new ol.style.Icon({
// url encoded svg icon to prevent cross-domain issues
src: "data:image/svg+xml;utf8,// center vertically at end of line
anchorXUnits: 'pixels',})
);
// end
var lastIndex = coords.length - 1;
var dx = coords[lastIndex - 1][0] - coords[lastIndex][0];
var dy = coords[lastIndex - 1][1] - coords[lastIndex][1];
var rotation = Math.atan2(dy,dx);
// end crossbar
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point(coords[lastIndex]),})
);
return styles;
};
var lineString = new ol.geom.LineString([
[-13015491.561823528,5172360.467799401],[-12379535.48649086,5182144.407419903]
])
// create the feature
var feature = new ol.Feature({
geometry: lineString,name: 'Line'
});
source.addFeature(feature);
var vector = new ol.layer.Vector({ // VectorLayer({
source: source,style: styleFunction,});
map.addInteraction(
new ol.interaction.Draw({
source: source,})
);
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
.map {
width: 100%;
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,URL"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
<link rel="stylesheet" href="https://openlayers.org/en/v6.5.0/css/ol.css" type="text/css">
<div id="map" class="map"></div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-162157-1";
urchinTracker();
</script>
</body>
</html>