【问题标题】:Draw multilinestring with ends in OpenLayers在 OpenLayers 中绘制带末端的多线串
【发布时间】:2021-05-28 05:34:45
【问题描述】:

我需要能够在 OpenLayers 5 中绘制多线串(这很容易),并带有可自定义的线端。

例如,如果我正在创建一个标尺工具,我希望多线串的末端是一个“T”,以准确显示线条的开始和结束位置。线条末端的“记号”必须是线条几何形状的一部分。

我已经这样构建了我的生产线......

  const draw: olDraw = new olDraw({
  source: MapValues.drawSource,
  type: 'LineString',
  style: new olStyle({
    fill: new olFill({
      color: 'rgba(255, 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);
}
}

【问题讨论】:

标签: openlayers openlayers-5


【解决方案1】:

您可以在 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>

【讨论】:

  • 迈克!!你摇滚!! 50分即将到来!
【解决方案2】:
  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]),
        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: [9.5, 0.5],
          anchorXUnits: 'pixels',
          rotateWithView: true,
          rotation: -rotation,
        }),
      })
    );
  return styles;
};

live example

代码 sn-p:

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', // '#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], // center vertically at end of line
        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]),
      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: [9.5, 0.5],
        anchorXUnits: 'pixels',
        rotateWithView: true,
        rotation: -rotation,
      }),
    })
  );
  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,
});

var map = new ol.Map({
  layers: [raster, vector],
  target: 'map',
  view: new ol.View({
    center: [-11000000, 4600000],
    zoom: 4,
  }),
});

map.addInteraction(
  new ol.interaction.Draw({
    source: source,
    type: 'LineString',
  })
);
/* 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>

  <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>

【讨论】:

  • 这很好,但有没有办法做到这一点,让整个东西成为一个多线字符串,末端添加线条而不是图标?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
  • 2011-02-13
  • 2023-03-25
相关资源
最近更新 更多