diff --git a/examples/feature-animation.html b/examples/feature-animation.html new file mode 100644 index 0000000000..6dd0795b36 --- /dev/null +++ b/examples/feature-animation.html @@ -0,0 +1,15 @@ +--- +template: example.html +title: Feature animation example +shortdesc: Demonstrates how to animate features. +docs: > + This example shows how to use postcompose and vectorContext to + animate features. Here we choose to do a flash animation each time a feature + is added to the layer. +tags: "animation, vector, feature, flash" +--- +
+
+
+
+
diff --git a/examples/feature-animation.js b/examples/feature-animation.js new file mode 100644 index 0000000000..00d97d98fc --- /dev/null +++ b/examples/feature-animation.js @@ -0,0 +1,96 @@ +goog.require('ol.Feature'); +goog.require('ol.Map'); +goog.require('ol.Observable'); +goog.require('ol.View'); +goog.require('ol.control'); +goog.require('ol.easing'); +goog.require('ol.geom.Point'); +goog.require('ol.layer.Tile'); +goog.require('ol.layer.Vector'); +goog.require('ol.proj'); +goog.require('ol.source.OSM'); +goog.require('ol.source.Vector'); +goog.require('ol.style.Circle'); +goog.require('ol.style.Stroke'); + + +var map = new ol.Map({ + layers: [ + new ol.layer.Tile({ + source: new ol.source.OSM({ + wrapX: false + }) + }) + ], + controls: ol.control.defaults({ + attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + collapsible: false + }) + }), + renderer: common.getRendererFromQueryString(), + target: 'map', + view: new ol.View({ + center: [0, 0], + zoom: 1 + }) +}); + +var source = new ol.source.Vector({ + wrapX: false +}); +var vector = new ol.layer.Vector({ + source: source +}); +map.addLayer(vector); + +function addRandomFeature() { + var x = Math.random() * 360 - 180; + var y = Math.random() * 180 - 90; + var geom = new ol.geom.Point(ol.proj.transform([x, y], + 'EPSG:4326', 'EPSG:3857')); + var feature = new ol.Feature(geom); + source.addFeature(feature); +} + +var duration = 3000; +function flash(feature) { + var start = new Date().getTime(); + var listenerKey; + + function animate(event) { + var vectorContext = event.vectorContext; + var frameState = event.frameState; + var flashGeom = feature.getGeometry().clone(); + var elapsed = frameState.time - start; + var elapsedRatio = elapsed / duration; + // radius will be 5 at start and 30 at end. + var radius = ol.easing.easeOut(elapsedRatio) * 25 + 5; + var opacity = ol.easing.easeOut(1 - elapsedRatio); + + var flashStyle = new ol.style.Circle({ + radius: radius, + snapToPixel: false, + stroke: new ol.style.Stroke({ + color: 'rgba(255, 0, 0, ' + opacity + ')', + width: 1, + opacity: opacity + }) + }); + + vectorContext.setImageStyle(flashStyle); + vectorContext.drawPointGeometry(flashGeom, null); + if (elapsed > duration) { + ol.Observable.unByKey(listenerKey); + return; + } + // tell OL3 to continue postcompose animation + frameState.animate = true; + } + listenerKey = map.on('postcompose', animate); +} + +source.on('addfeature', function(e) { + flash(e.feature); +}); + +window.setInterval(addRandomFeature, 1000);