meface/docs/article/gis/openlayers/13viewexample.md

9.0 KiB
Raw Blame History

title date author tags categories
View 示例 2021-09-08 ac
OpenLayers
GIS

View Animation 示例

开始学ol会觉得很奇怪,因为从ArcGIS API for JS 3.x刚转过来它里面并没有将控制分辨率、缩放级别、地图范围、投影等分离出来这些相关的API全在map对象里面ol将它们封装到了View中。

1 View对象

View对象是代表地图的简单2D视图可以用于更改地图中心、分辨率、和旋转的对象其中的projection属性确定地图的坐标系默认是墨卡托投影EPSG:3857)。

View有三种状态

  • center视图的初始中心。
  • resolution视图的初始分辨率。单位是projection每像素的单位例如米/像素),所有关于地图缩放有关的计算都是使用resolution
  • rotation视图的初始旋转弧度顺时针正旋转0表示北

跟地图缩放有关的还有zoom属性,但实际上zoom没有封装在view对象中,不过view中还是提供了setZoom()getZoom()方法访问zoom属性。

2 状态的限制

通过setCentersetResolutionsetRotation方法可以改变view的状态。但地图不可能无限的放大或缩小所以使用resolutions设置地图的所有层级的分辨率或使用maxResolutionMaxZoomzoomFactor限制缩放的大小。如果设置了resolutions属性,其他三个属性将失效。

3 Animation动画

当改变view状态的时候可以使用animate(option)方法从原来的状态平滑的过渡到另一个状态。

option配置对象,以JSON对象的方式配置参数,同时也可以有多个配置对象形成链式连续的动画效果。

type Description
center 动画结束后view的中心
zoom 动画结束后view的缩放级别优先于resolution
resolution 动画结束后view的地图分辨率如果设置了zoom则该配置项会被忽略
rotation 动画结束后view的旋转角度顺时针正旋转0表示北
anchor 锚点是一个Coordinate类型的参数用于固定某点进行动画
duration 动画的过渡时间,单位为毫米
easing 动画使用的缓冲函数。该函数将为每一帧调用并带有表示动画持续时间的一小部分的数字。应该返回一个0到1之间的数字表示向目标状态的进展。
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <style>
      .map {
        height: 400px;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css">
    <title>View</title>
  </head>
  <body>
    <h2>My Map</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript">

    window.onload =function(){
        var shenzhen = [113.958334,22.535640];
        /*
         * 地图表现:必备三要素,
         * 图层Layer
         * 视图View
         * 目标容器target
         * */
        var map = new ol.Map({
          view:new ol.View({
            center:ol.proj.fromLonLat(shenzhen),
            zoom:8,
            minzoom:6,
            maxzoom:12,
            rotation:Math.PI/6
          }),
          layers:[
            new ol.layer.Tile({
              source:new ol.source.OSM()
            })
          ],
          target:"map"
        });
        map.on("click",function (e) {
          var point = e.coordinate;
          console.log("x:"+point[0]+",y:"+point[1]);
        });
        /*
        *View对象
        *View对象是代表地图的简单2D视图可以用于更改地图中心、分辨率、和旋转的对象
        * projection属性确定中心的坐标系默认是墨卡托投影EPSG:3857
        *
        * View三种状态
        * center视图的初始中心。如果未设置用户投影则使用projection选项指定中心的坐标系如果未设置则不会获取图层源但是稍后可以使用设置中心#setCenter。
        * resolution视图的初始分辨率。单位是projection每像素的单位例如米/像素)
        * rotation视图的初始旋转弧度顺时针正旋转0表示北        *
        * 常用属性还有zoom,resolutions。如果设置了resolutions则maxResolutionminResolution minZoommaxZoom和zoomFactor选项都将被忽略。
        */
        //地图视图的初始化参数
        var view = map.getView();
        var zoom = view.getZoom();
        var center = view.getCenter();
        var rotation = view.getRotation();

        document.getElementById("zoom-out").onclick = function(e){
          var view = map.getView();
          var zoom = view.getZoom();
          view.setZoom(zoom - 1);
        };

        document.getElementById("zoom-in").onclick = function(e){
          var view = map.getView();
          var zoom = view.getZoom();
          view.setZoom(zoom + 1);
        };

        document.getElementById("panto").onclick = function(e){
          var view = map.getView();
          //参数为ol.Coordinate
          var mak =  ol.proj.fromLonLat(shenzhen);
          view.setCenter(mak);
        };

        document.getElementById("reset").onclick = function(e){
          view.setCenter(center);
          view.setZoom(zoom);
          view.setRotation(rotation);
        };

        // var shenzhen = [1280091112800911.302100137,2611260.0825854577];
        /*
        animate(var_args)
        例子: view.animate({zoom: view.getZoom() + 1});
              view.animate({zoom: 10}, {center: [0, 0]});将多个动画放在一起,先缩放后平移

        参数center、zoom、resolution、rotation、duration、easing、anchor
             默认情况下,动画持续一秒钟,并 in-and-out easing缓进缓出
             duration设置动画持续时间单位毫秒
             easing设置动画进出方式
             anchor锚点用于rotation或resolution固定旋转的原点
        **/
        document.getElementById("rotate-left").onclick = function (e) {
          view.animate({
            rotation:view.getRotation()+Math.PI/2
          });
        };

        document.getElementById("rotate-right").onclick = function (e) {
          view.animate({
            rotation:view.getRotation()-Math.PI/2
          });
        };

        document.getElementById("fly-to-shenzhen").onclick = function () {
          var rotation = view.getRotation();
          flyTo(shenzhen,function () {
            console.log("执行完回调");
          });
        };
        function flyTo(location, done) {
          var duration = 2000;
          var zoom = view.getZoom();
          var parts = 2;
          var called = false;
          function callback(complete) {
            --parts;
            if (called) {
              return;
            }
            if (parts === 0 || !complete) {
              called = true;
              done(complete);
            }
          }
          view.animate({
            center: ol.proj.fromLonLat(shenzhen),
            duration: duration
          }, callback);
          view.animate({
            zoom: zoom - 1,
            duration: duration / 2
          }, {
            zoom: zoom,
            duration: duration / 2
          }, callback);
        }

        /**
         * 注意当多个option配置对象时每个状态zoomresolutionrotation都是相对原始状态的
         */
        document.getElementById("rotate-around-shenzhen").onclick = function(){
            var rotation = view.getRotation();
            view.animate({
                rotation: rotation + Math.PI,//是原始状态旋转180
                anchor: ol.proj.fromLonLat(shenzhen),
                easing: ol.easing.easeIn
            },{
                rotation: rotation + 2*Math.PI,//是原始状态旋转360
                anchor: ol.proj.fromLonLat(shenzhen),
                easing: ol.easing.easeOut
            })
        }
      }
    </script>
    <hr>
    <div>
      <p>View动画animation</p>
      <p>让View平滑地改变状态中心点、缩放级别、旋转</p>
      <button id="zoom-out">放大</button>
      <button id="zoom-in">缩小</button>
      <button id="panto">定位</button>
      <button id="reset">复位</button>
      <button id="rotate-left" title="Rotate clockwise"></button>
      <button id="rotate-right" title="Rotate counterclockwise"></button>
      <button id="rotate-around-shenzhen">Rotate around shenzhen</button>
      <button id="fly-to-shenzhen">Fly to ShenZhen</button>
    </div>
  </body>
</html>