How to draw linestring from consecutive points of array in openlayers

杀马特。学长 韩版系。学妹 提交于 2019-12-11 10:42:16

问题


I am trying to draw LineString in openlayers with consecutive Points to give it a feel of animation like it is drawing from start to end.

I tried to achieve it by following this example. All references of OL2 are converted to OpenLayers 5, but still drawing should happen one point followed by next for entire array and not at once.

Find my code with current output here - my code.

[For reference] This is I am trying to achieve Snake animation for leaflet.


回答1:


Using only the vertices of a linestring doesn't give a smooth animation. You can see that in the OpenLayers example https://openlayers.org/en/v4.6.5/examples/feature-move-animation.html where the marker moves much faster over the straight sections. If you need smooth movement along straight lines as in the OpenLayers 2 example you need to use .getCoordinateAt() to calculate where on the line you should be at any time. Here's a demo based on the marker animation example but also calculating positions between vertices showing the linestring from the snake example. You can also draw you own straight lines and watch them animate smoothly.

var style = new ol.style.Style({
  stroke: new ol.style.Stroke({
width: 4,
color: 'red'
  })
});

var raster = new ol.layer.Tile({
  source:  new ol.source.OSM()
});

var vector = new ol.layer.Vector({
  source: new ol.source.Vector(),
  style: style
});

var map = new ol.Map({
  layers: [raster, vector],
  target: 'map',
  view: new ol.View()
});

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://raw.githubusercontent.com/IvanSanchez/Leaflet.Polyline.SnakeAnim/master/route.js');
xhr.onload = function() {
  // read the route coordinates
  eval(xhr.responseText);
  // reverse the route
  var geom = new ol.geom.LineString(route.reverse());
  // change Lat/Lon to Lon/Lat
  geom.applyTransform(function(c){ return c.reverse(); });
  geom.transform('EPSG:4326', map.getView().getProjection());
  map.getView().fit(geom.getExtent(), { size: map.getSize() });
  var snake = new ol.Feature();
  vector.getSource().addFeature(snake);
  animate_line(snake, geom, 30000);
}
xhr.send();

function animate_line(feature, linestring, duration) {

  var length = linestring.getLength();
  var length_shown = 0;

  var coords = linestring.getCoordinates();
  var coords_shown = [coords[0], coords[0]];
  var geom_shown = new ol.geom.LineString(coords_shown);
  feature.setGeometry(geom_shown);

  var coordcount = 1;
  var start = new Date().getTime();
  var listenerKey = map.on('postcompose', animate);

  function animate() {

var elapsed = new Date().getTime() - start;
var toAdd = length*elapsed/duration - length_shown;
var point = linestring.getCoordinateAt(Math.min(elapsed/duration, 1));

// restart from last intermediate point and remove it
var newPart = new ol.geom.LineString(coords_shown.slice(-1));
coords_shown.pop();

// add vertices until required length exceeded
while (coordcount < coords.length && newPart.getLength() <= toAdd) {
  newPart.appendCoordinate(coords[coordcount]);
  coords_shown.push(coords[coordcount]);
  coordcount++;
}

// replace overrun vertex with intermediate point
coords_shown.pop();
coordcount--;
coords_shown.push(point);

geom_shown.setCoordinates(coords_shown);
length_shown += toAdd;

if (elapsed > duration) {
  ol.Observable.unByKey(listenerKey);
}
map.render();

  }

}

draw = new ol.interaction.Draw({
  source: vector.getSource(),
  type: 'LineString'
});

draw.on('drawend',function(evt){
  geom = evt.feature.getGeometry();
  evt.feature.setGeometry(undefined);
  animate_line(evt.feature, geom, 6000);
});
map.addInteraction(draw);
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>



回答2:


Your for loop

for(i=0;i<path.length;) {
    drawAnimatedLine(/*snip*/);
}

starts the animation for all points basically at the same time without waiting. You'll need to wait until the animation of the first line is finished before starting the next segment. Your drawAnimation function has a 6th parameter fn to provide it with a function pointer of a function to call when drawing is finished.

Here's a quick an dirty version where I rewrote your for loop to demonstrate, what I mean. https://jsbin.com/lanoxojugi/edit?js,output



来源:https://stackoverflow.com/questions/55587144/how-to-draw-linestring-from-consecutive-points-of-array-in-openlayers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!