Openlayers 3 Feature Animation

HTML

<script src="https://openlayers.org/en/v3.15.1/build/ol.js"></script>
<link rel="stylesheet" href="https://openlayers.org/en/v3.15.1/css/ol.css">
<div id="map" class="map"></div>
<button id="stopBtn">Stop</button>

CSS

#map
{
  background-color: red;
}

JavaScript

var source = new ol.source.Vector({});

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

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

var feature = new ol.Feature({
  geometry: new ol.geom.Circle([0, 0], 1)
});

source.addFeature(feature);

// Animation
var duration = 1500;
var minOpacity = 0.3;
var maxOpacity = 1;
var opacityRatio = ((maxOpacity - minOpacity) / (duration /2));
var listenerKey = map.on('postcompose', animate);

var start = new Date().getTime();

function animate (event)
{
  var vectorContext = event.vectorContext;
  var frameState = event.frameState;
  
  var elapsed = frameState.time - start;
  
	var opacity;
  
  if (elapsed > (duration / 2))
  {
  	opacity = minOpacity + (opacityRatio * (elapsed - (duration / 2)));
  }
  else
  {
  	opacity = maxOpacity - (opacityRatio * elapsed);
  }
  
  var style = new ol.style.Style({
  	stroke: new ol.style.Stroke({
      color: 'rgba(252, 237, 33, ' + opacity + ')',
      width: 6
    })
  });
   
  feature.setStyle(style);
  
  if (elapsed > duration)
  {
    start = new Date().getTime();
  }
}

document.querySelector('#stopBtn').addEventListener('click', function (event)
{
	ol.Observable.unByKey(listenerKey);
});