简体   繁体   中英

How to draw linestring from consecutive points of array in openlayers

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 .

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> 

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM