高德3D动态地图—旋转视角

做这个动态效果之前,大家可以了解下高地的官方示例(https://lbs.amap.com/demo/loca-v2/demos/cat-view-control/view-control)高德提供了镜头旋转的官方示例,但是镜头旋转没有说明,而且存在bug,调整speed速度后整个场景就乱了,因为我能力有限而且比较懒,所以我开始自己写动画。

高德3D动态地图—旋转视角

地图使用2.0的版本(http://webapi.amap.com/maps?v=2.0),之前使用1.4.3的版本在旋转是存在周边空白,又没找到刷新的方法,所以使用当前最新的2.0版本。将整个动画划分为四步:

第一步,加载,2.0版本首次加载时如果不预留加载时间,地图标记点不会显示。判断是否首次加载,首次加载不旋转,非首次旋转

第二步,调整视角到2D视角

第三步,2D视角进行旋转一定时间

第四步,重新旋转回到3D视角

这四步需要处理的几个问题:

1、通过requestAnimationFrame方法循环处理每一帧的动画。

2、控制FPS(每秒帧数),防止帧数太高,电脑发热

3、处理旋转一周后,高德反转导致的回放

下面是示例代码,有兴趣自己看吧(把key替换成自己的

<script src="http://webapi.amap.com/maps?v=2.0&key=改成自己的&plugin=Map3D,AMap.DistrictLayer,AMap.DistrictSearch,AMap.Scale,AMap.ToolBar"></script>
<script src="http://webapi.amap.com/loca?v=2.0.4&key=改成自己的"></script>

<html>
<head>
    <title>牟云飞示例</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta id="viewport" name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0"/>

    <link type="text/css" rel="styleSheet"  href="css/fatterStyle3D.css" />
    <style>

        .infowindow_custom_geo{


        }
        .infowindow_custom_geoContent{
            display: flex;
            flex-direction:column;
            justify-content: center;/*实现水平居中*/
        }
        .infowindow_custom_geoContent_fontcolor{
            color:RGB(21,253,255);
            height: 30px;
        }

        /*从左到右进入*/
        .fadeInLeft {
            animation: fadeInLeft 0.8s ;
            -webkit-animation: fadeInLeft 0.8s ;
        }
        @keyframes fadeInLeft
        {
            from {
                opacity: 0;
                -webkit-transform: translate(-1000px,0);
                transform: translate(-1000px,0);
            }
            to {
                opacity:1;
                -webkit-transform: translate(10px,0);
                transform: translate(10px,0);
            }
        }

        @-webkit-keyframes fadeInLeft
        {
            from {
                opacity:0;
                -webkit-transform: translate(-1000px,0);
                transform: translate(-1000px,0);
            }
            to {
                opacity:1;
                -webkit-transform: translate(10px,0);
                transform: translate(10px,0);
            }
        }

        /*从右到左进入*/
        .fadeInRight {
            animation: fadeInRight 0.8s ;
            -webkit-animation: fadeInRight 0.8s ;
        }
        @keyframes fadeInRight
        {
            from {
                opacity: 0;
                -webkit-transform: translate(1000px,0);
                transform: translate(1000px,0);
            }
            to {
                opacity:1;
                -webkit-transform: translate(10px,0);
                transform: translate(10px,0);
            }
        }

        @-webkit-keyframes fadeInRight
        {
            from {
                opacity:0;
                -webkit-transform: translate(1000px,0);
                transform: translate(1000px,0);
            }
            to {
                opacity:1;
                -webkit-transform: translate(10px,0);
                transform: translate(10px,0);
            }
        }



    </style>
</head>
<body>
<div id="topDiv" >
    <div id="containerMap"></div>
</div>
<script src="http://webapi.amap.com/maps?v=2.0&key=改成自己的&plugin=Map3D,AMap.DistrictLayer,AMap.DistrictSearch,AMap.Scale,AMap.ToolBar"></script>
<script src="http://webapi.amap.com/loca?v=2.0.4&key=改成自己的"></script>


<script type="text/javascript">

    var myMap_zhdp;
    var box_zhdp, network_zhdp, baiduMap_zhdp;
    var node_colors = ['#259B24','#2DC1B4','#FF9800','#005E7D','#BF2DC1','#FF0000','#6184F0'];
    var layer = null;//撒点
    var markers = [];
    var mapDataArr = [];


    var initData = {
        "parameters": {
            "mapData": {
                "greenhouse": [
                    {
                        "latitude": "36.793139",
                        "longitude": "118.682124",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    },
                    {
                        "latitude": "36.90723878",
                        "longitude": "118.86398011",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "scenicspot": [
                    {
                        "latitude": "37.070134",
                        "longitude": "118.696025",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "livestockCultivation": [
                    {
                        "latitude": "36.972933",
                        "longitude": "118.89215",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "seafoodCultivation": [
                    {
                        "latitude": "37.186281",
                        "longitude": "118.751003",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "heating": [
                    {
                        "latitude": "36.801139",
                        "longitude": "118.830124",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "fruitProcessing": [
                    {
                        "latitude": "36.861139",
                        "longitude": "118.680124",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ],
                "zhxxInfo": [
                    {
                        "latitude": "36.791139",
                        "longitude": "118.680124",
                        "info": {
                            "name": "牟云飞示例1",
                        }
                    }
                ]
            }
        },
        "dataWraps": { },
        "errorMessage": "",
        "message": "",
        "exportFileName": null,
        "currentDataWrap": "dataWrap",
        "exportColumns": null,
        "metaData": null
    }




    var obj =initData.parameters.mapData;

    function initMap(obj){
        console.log("obj:",obj);
        myMap_zhdp = new AMap.Map("containerMap", {
            viewMode: '3D',
            mapStyle: 'amap://styles/90287222547b179fcbda2e63865f2f5c',
            showBuildingBlock: true,
            //center: [118.848014,36.885728],
            center: [118.848014,37.085728],
            pitch: 80,
            zoom: 11,
//            layers: [
//                // 卫星
//                new AMap.TileLayer.Satellite(),
//                // 路网
//                new AMap.TileLayer.RoadNet()
//            ]
        });
        //为地图注册click事件获取鼠标点击出的经纬度坐标
        myMap_zhdp.on('click', function(e) {
            console.log(e.lnglat.getLng() + ',' + e.lnglat.getLat());
        });

        //创建区域
        createArea();
        //散点
        layer = new AMap.LabelsLayer({
            zooms: [3, 20],
            zIndex: 1000,
            // 开启标注避让,默认为开启,v1.4.15 新增属性
            collision: false,
            // 开启标注淡入动画,默认为开启,v1.4.15 新增属性
            animation: true,
        });
        addnodes(obj.greenhouse,0);
        addnodes(obj.scenicspot,1);
        addnodes(obj.livestockCultivation,2);
        addnodes(obj.seafoodCultivation,3);
        addnodes(obj.heating,4);
        addnodes(obj.fruitProcessing,5);
        var zhxxInfo = obj.zhxxInfo;
        addnodes(zhxxInfo,6);

        myMap_zhdp.add(layer);



        myMap_zhdp.on('complete', function () {
            //地图加载完成后

            render();
        });
    }

    //添加地图节点
    function addnodes(obj,index) {
        if(obj==null) return;
        for(var i=0;i<obj.length;i++){
            var curData = {
                name: obj[i].info.name,
                position: [obj[i].longitude, obj[i].latitude],
                zooms: [3, 20],
                opacity: 1,
                zIndex: 10,
                icon: {
                    type: 'image',
                    image: '../images/mapImages/poi-marker.png',
                    clipOrigin: [14, 92],
                    clipSize: [50, 68],
                    size: [25, 34],
                    anchor: 'bottom-center',
                    angel: 0,
                    retina: true
                },
                text: {
                    content: obj[i].info.name,
                    direction: 'left',
                    offset: [0, -5],
                    style: {
                        fontSize: 15,
                        fontWeight: 'normal',
                        fillColor: node_colors[index],
                        strokeColor: '#fff',
                        strokeWidth: 2,
                    }
                }
            };
            //console.log("-----------obj:",obj);

            var labelMarker = new AMap.LabelMarker(curData);
            markers.push(labelMarker);
            mapDataArr.push(obj[i]);
            //console.log("-----------labelMarker:",labelMarker);
            layer.add(labelMarker);
        }
    }

    //划分区域
    var district = null;
    var polygons=[];
    function createArea() {
        if(!district){
            //实例化DistrictSearch
            var opts = {
                subdistrict: 0,   //获取边界不需要返回下级行政区
                extensions: 'all',  //返回行政区边界坐标组等具体信息
                level: 'district'  //查询行政级别为 市
            };
            district = new AMap.DistrictSearch(opts);
        }
        //行政区查询
        district.search("寿光市", function(status, result) {
            myMap_zhdp.remove(polygons)//清除上次结果
            polygons = [];
            var bounds = result.districtList[0].boundaries;
            if (bounds) {
                for (var i = 0, l = bounds.length; i < l; i++) {
                    //生成行政区划polygon
                    var polygon = new AMap.Polygon({
                        strokeWeight: 1,
                        path: bounds[i],
                        fillOpacity: 0.2,
                        fillColor: '#80d8ff',
                        strokeColor: '#0091ea'
                    });
                    polygons.push(polygon);
                }
            }
            myMap_zhdp.add(polygons);
        });
    }




    /**
     * -----------------------------
     * 动画事件,时钟
     * -----------------------------
     */
    class fatterClock {
        constructor( autoStart ) {
            this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
            this.startTime = 0;
            this.oldTime = 0;
            this.elapsedTime = 0;
            this.running = false;
        }
        start() {
            this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
            this.oldTime = this.startTime;
            this.elapsedTime = 0;
            this.running = true;
        }
        stop() {
            this.getElapsedTime();
            this.running = false;
            this.autoStart = false;
        }
        getElapsedTime() {
            this.getDelta();
            return this.elapsedTime;
        }
        getDelta() {
            let diff = 0;
            if ( this.autoStart && ! this.running ) {
                this.start();
                return 0;
            }
            if ( this.running ) {
                const newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
                diff = ( newTime - this.oldTime ) / 1000;
                this.oldTime = newTime;
                this.elapsedTime += diff;
            }
            return diff;
        }
    }

    /**
     * -----------------------------
     * 动画事件
     * -----------------------------
     */
    var mapStep = 0;
    var waitTime = 90;
    var curWaitTime = 0;
    var isFirst = true ;//判断是否第一次加载,第一次加载进入等待期,防止一开始不加载图层
    var mapRotationInitControl = false;//判断是否开启回正旋转角度模式,如果超过360度,高德不会继续顺时针旋转,高德会逆时针旋转到0
    function mapAnimate(map,callbackParam,beginPoi,endPoi){

        //动画前关闭展示框
        //hideInfoWindow();


        var _curPitch = map.getPitch();
        var _curZoom = map.getZoom();
        var _curRotation = map.getRotation();

        var _pitchSpeed = 0.5;
        var _zoomSpeed = 0.02;
        var _rotationSpeed = 0.1;

        //进入等待期,防止一开始不加载图层
        if(mapStep == 0 ){
            /* if(curWaitTime<=waitTime){
             curWaitTime = curWaitTime + 1;
             }else{
             mapStep = 1;
             curWaitTime = 0;
             isFirst = false;
             }
             if(isFirst == false){
             map.setRotation((_curRotation + _rotationSpeed)%360);
             } */


            curWaitTime = curWaitTime + 1;


            //如果超过360度,高德不会继续顺时针旋转,高德会逆时针旋转到0
            if(isFirst == false&&(_curRotation + _rotationSpeed)<360 && mapRotationInitControl==false){
                map.setRotation((_curRotation + _rotationSpeed)%360);
            }else if(isFirst == false){
                map.setRotation((_curRotation - _rotationSpeed*6)%360);
                mapRotationInitControl = true;//开启旋转角度回正控制
            }
            //开启角度回正模式后,判断是否已经回正旋转角度
            if(mapRotationInitControl==true&&_curRotation<10){
                mapRotationInitControl = false;
            }

            if(curWaitTime>waitTime&&mapRotationInitControl==false){
                mapStep = 1;
                curWaitTime = 0;
                isFirst = false;
            }
        }

        //第一阶段,回2d地图
        if(mapStep==1){
            //回正地图
            let _flag = 3;
            if(_curPitch>1){
                map.setPitch(_curPitch - _pitchSpeed);
                _flag = _flag - 1;
            }
            //缩小尺寸
            if(_curZoom>10){
                map.setZoom(_curZoom - _zoomSpeed);
                _flag = _flag - 1;
            }
            //if(_curRotation<20){
            //map.setRotation((_curRotation + _rotationSpeed)%360);
            //_flag = _flag - 1;
            //}
            map.setCenter([118.848014,36.985728]);
            if(_flag == 3){
                //进入下一阶段
                mapStep = 2;
            }
        }

        //进入等待期
        if(mapStep == 2 ){

            curWaitTime = curWaitTime + 1;


            //如果超过360度,高德不会继续顺时针旋转,高德会逆时针旋转到0
            if(isFirst == false&&(_curRotation + _rotationSpeed)<360 && mapRotationInitControl==false){
                map.setRotation((_curRotation + _rotationSpeed)%360);
            }else{
                map.setRotation((_curRotation - _rotationSpeed*6)%360);
                mapRotationInitControl = true;//开启旋转角度回正控制
            }
            //开启角度回正模式后,判断是否已经回正旋转角度
            if(mapRotationInitControl==true&&_curRotation<10){
                mapRotationInitControl = false;
            }

            if(curWaitTime>waitTime&&mapRotationInitControl==false){
                mapStep = 3;
                curWaitTime = 0;
            }

        }


        //回到3D地图
        if(mapStep == 3 ){

            let _flag = 3;
            if(_curPitch<=75){
                map.setPitch(parseFloat(_curPitch + _pitchSpeed));
                _flag = _flag - 1;
            }
            //缩小尺寸
            if(_curZoom<=11.5){
                map.setZoom(parseFloat(_curZoom + _zoomSpeed*3));
                _flag = _flag - 1;
            }

            //如果超过360度,高德不会继续顺时针旋转,高德会逆时针旋转到0
            if(isFirst == false&&(_curRotation + _rotationSpeed*10)<360 && mapRotationInitControl==false){
                map.setRotation((_curRotation + _rotationSpeed*10)%360);
            }else{
                map.setRotation((_curRotation - _rotationSpeed*20)%360);
                mapRotationInitControl = true;//开启旋转角度回正控制
            }
            //开启角度回正模式后,判断是否已经回正旋转角度
            if(mapRotationInitControl==true&&_curRotation<10){
                mapRotationInitControl = false;
            }

            if(_flag == 3&&mapRotationInitControl==false){
                mapStep = 0;
            }


        }

    }


    //渲染
    var timeInteval = 200; //20为1秒,浏览器不同,事件不一定,用于地图
    var curTimeInteval = 20;//,用于地图
    var curGeoPoint = 0;//,用于地图

    var clock = new fatterClock();
    var timeS = 0;//控制间隔时间
    var FPS = 60;
    var renderT = 1 / FPS; //单位秒  间隔多长时间渲染渲染一次
    function render(){
        let T = clock.getDelta()
        timeS = timeS + T;
        if (timeS > renderT) {

            //整个场景动起来
            if(null!=myMap_zhdp&&null!=mapDataArr&&0!=mapDataArr.length){
                if(curTimeInteval>=timeInteval){
                    curTimeInteval = 0;//重置
                    curGeoPoint++;
                    if(curGeoPoint>=mapDataArr.length){
                        curGeoPoint = 0;
                    }
                }
                //getPosition( )
                var _temp = mapDataArr[curGeoPoint];
                //console.log("++++++_temp:",_temp);
                //场景动画
                mapAnimate(
                        myMap_zhdp,
                        {
                            'curId': _temp.info.code,
                            'curCustomObj_center': new AMap.LngLat( _temp.longitude,_temp.latitude),
                            'customObj_height': -_temp.info.greenHouseCount
                        },null,new AMap.LngLat( _temp.longitude,_temp.latitude)
                );

            }
            curTimeInteval++;

            //控制渲染的帧数
            timeS = 0;
        }

        //动画
        requestAnimationFrame(render);

    }


    initMap(obj);

</script>
</body>
</html>

 

上一篇:css 文本溢出显示...


下一篇:要做自定义滚动条就要做到最好的scroll-div