在 OpenLayers 中绘制多线串

问题描述

我需要能够在 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>

,
  1. 制作一个图标,作为行尾的横杆:
横杆图标
"crossbar" icon
  1. 将其添加到 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;
};

live example

screenshot of map

代码片段:

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>