动画高阶应用

虽然内置动画并不多,但是细心的同学已经发现了内置动画有个参数easing,这是一个强大的参数,因为可以让开发者自定义动画实现,从而实现动画效果的扩展。 其实已经内置了一些相关的实现,在ol.easing里面,涉及到一些常用的效果,包括:

  • ol.easing.easeIn: 加速
  • ol.easing.easeOut: 减速
  • ol.easing.inAndOut: 先加速再减速
  • ol.easing.linear: 匀速
  • ol.easing.upAndDown: 和inAndOut类似

在前面的地图的基础上修改一下,让大家体验一下不同的动画的效果:

尝试完所有的动画方式后,可以看一下其实现代码:

<div id="map" style="width: 100%"></div>
<!--添加动画效果选择项-->
<select id = "easing-type">
    <option>easeIn</option>
    <option>easeOut</option>
    <option>inAndOut</option>
    <option>linear</option>
    <option>upAndDown</option>
</select>
<input type="button" value="回到原点" onclick="backWithAnim()"></input>
<script type="text/javascript">
    var map = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          })
        ],
        target: 'map',
        view: new ol.View({
          center: ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'),
          zoom: 10
        })
    });

    // 根据选择项,返回对应的动画,供下面的backWithAnim函数使用
    function getEasing() {
        var typeSelect = document.getElementById('easing-type');
        var easing = typeSelect.options[typeSelect.selectedIndex].text;
        if (easing === 'easeIn') {
            return ol.easing.easeIn;
        } else if (easing === 'easeOut') {
            return ol.easing.easeOut;
        } else if (easing === 'inAndOut') {
            return ol.easing.inAndOut;
        } else if (easing === 'linear') {
            return ol.easing.linear;
        } else if (easing === 'upAndDown') {
            return ol.easing.upAndDown;
        } 
    }

    function backWithAnim() {
        var pan = ol.animation.pan({
      duration: 2000,
      source: map.getView().getCenter(),
      easing: getEasing()    // 设置对应选择的动画
    });
    map.beforeRender(pan);
    map.getView().setCenter(ol.proj.transform([104, 30], 'EPSG:4326', 'EPSG:3857'));
    }

</script>

通过上面这种方法,我们完全可以自定义动画函数,通过官网API文档可知,这些函数有一个参数t,范围在0-1之间,然后函数返回一个0-1之间的数。 结合动画业务来看,虽然官网没有说明参数表示什么意思,但是我们可以猜测它就是时间,返回的值应该目标达成比。 下面我们自己来实现一个sin曲线式的动画:

速度一开始会快一点,然后慢下来, 对应的代码如下:

<div id="map2" style="width: 100%"></div>
<input type="button" value="回到原点" onclick="backWithAnim2();"></input>
<script type="text/javascript">
    var map2 = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          })
        ],
        target: 'map2',
        view: new ol.View({
          center: ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'),
          zoom: 10
        })
    });

    // sin曲线动画
    function sin(t) {
        // 使用sin曲线公式
        return Math.sin(t * Math.PI / 2);
    }

    function backWithAnim2() {
        var pan = ol.animation.pan({
      duration: 2000,
      source: map2.getView().getCenter(),
      easing: sin // 应用sin曲线动画
    });
    map2.beforeRender(pan);
    map2.getView().setCenter(ol.proj.transform([104, 30], 'EPSG:4326', 'EPSG:3857'));
    }

</script>