8-地圖切換動(dòng)畫

本博客合集是我的openlayers學(xué)習(xí)筆記,希望能幫助到剛開(kāi)始接觸openlayers的同學(xué)
@commnet 所用openlayers版本:v5.3.0
@commnet 閱讀本文前需要對(duì)前端知識(shí)有一定的了解
@comment 本文內(nèi)容只提供參考,建議結(jié)合openlayers官網(wǎng)的APIexamples來(lái)學(xué)習(xí)
@comment 部分代碼參考了@老胡

動(dòng)畫即過(guò)渡動(dòng)畫,如果沒(méi)有動(dòng)畫,地圖從一個(gè)view狀態(tài)切換到另一個(gè)view狀態(tài)是突變的、死板的,動(dòng)畫能使過(guò)渡效果更自然。

本節(jié)內(nèi)容主要用到了view對(duì)象的animate方法,下面以實(shí)例說(shuō)明。

  • 創(chuàng)建幾個(gè)功能測(cè)試按鈕和一個(gè)地圖容器
<button id="rotate-left" title="順時(shí)針旋轉(zhuǎn)">?</button>
<button id="rotate-right" title="逆時(shí)針旋轉(zhuǎn)">?</button>
<button id="pan-to-london">平移到倫敦</button>
<button id="elastic-to-moscow">彈性平移到莫斯科</button>
<button id="bounce-to-istanbul">彈跳平移到伊斯坦布爾</button>
<button id="spin-to-rome">旋轉(zhuǎn)平移到羅馬</button>
<button id="rotate-around-rome">繞著羅馬旋轉(zhuǎn)</button>
<button id="fly-to-bern">飛行到伯爾尼</button>
<button id="tour">來(lái)一段旅行</button>
<div id="map" class="map"></div>
  • 創(chuàng)建地圖對(duì)象和幾個(gè)城市的偽墨卡托坐標(biāo)變量,還有一個(gè)為按鈕添加點(diǎn)擊事件的函數(shù),方便后續(xù)調(diào)用
var london = ol.proj.fromLonLat([-0.12755, 51.507222]);//倫敦
var moscow = ol.proj.fromLonLat([37.6178, 55.7517]);//莫斯科
var istanbul = ol.proj.fromLonLat([28.9744, 41.0128]);//伊斯坦布爾
var rome = ol.proj.fromLonLat([12.5, 41.9]);//羅馬
var bern = ol.proj.fromLonLat([7.4458, 46.95]);//柏林

var view = new ol.View({
    center: istanbul,
    zoom: 6
});

var map = new ol.Map({
    target: 'map',
    layers: [
        new ol.layer.Tile({
            preload: 4,
            source: new ol.source.OSM()
        })
    ],
    //開(kāi)啟動(dòng)畫時(shí)允許加載瓦片數(shù)據(jù)
    loadTilesWhileAnimating: true,
    view: view
});

function onClick(id, callback) {
    document.getElementById(id).addEventListener('click', callback);
}
  • 通過(guò)rotation參數(shù)設(shè)置地圖的旋轉(zhuǎn)動(dòng)畫

在animate中傳入想要變化的view的目標(biāo)參數(shù)(如rotation、center),從當(dāng)前狀態(tài)變化到目標(biāo)狀態(tài)時(shí),如不指定動(dòng)畫類型,地圖會(huì)使用默認(rèn)方式渲染動(dòng)畫。

onClick('rotate-left', function() {
    //設(shè)置rotation參數(shù)的目標(biāo)值為當(dāng)前角度順時(shí)針加90度,地圖會(huì)以默認(rèn)方式渲染動(dòng)畫
    view.animate({
        rotation: view.getRotation() + Math.PI / 2
    });
});

onClick('rotate-right', function() {
    //設(shè)置rotation參數(shù)的目標(biāo)值為當(dāng)前角度順時(shí)針減90度,地圖會(huì)以默認(rèn)方式渲染動(dòng)畫
    view.animate({
        rotation: view.getRotation() - Math.PI / 2
    });
});
  • 入場(chǎng)動(dòng)畫和出場(chǎng)動(dòng)畫

地圖過(guò)渡的一段動(dòng)畫可以同時(shí)包括入場(chǎng)動(dòng)畫和出場(chǎng)動(dòng)畫,在同一animate函數(shù)中指定。下面的例子中,入場(chǎng)動(dòng)畫為先慢后快地以羅馬為中心、將地圖順時(shí)針旋轉(zhuǎn)180度,出場(chǎng)動(dòng)畫為先快后慢地以羅馬為中心、繼續(xù)順時(shí)針旋轉(zhuǎn)至360度。

onClick('rotate-around-rome', function() {
    var rotation = view.getRotation();
    view.animate(
    //入場(chǎng)動(dòng)畫為順時(shí)針旋轉(zhuǎn)180度
    {
        rotation: rotation + Math.PI,
        anchor: rome,//圍繞羅馬旋轉(zhuǎn)
        easing: ol.easing.easeIn//擦除方式使用先慢后快的ol.easing.easeIn
    }, 
    //出場(chǎng)動(dòng)畫為順時(shí)針旋轉(zhuǎn)360度
    {
        rotation: rotation + 2 * Math.PI,
        anchor: rome,
        easing: ol.easing.easeOut//擦除方式使用先快后慢的ol.easing.easeOut
    });
});
  • 通過(guò)center參數(shù)設(shè)置地圖的移動(dòng)動(dòng)畫

下面的例子展示了地圖以默認(rèn)動(dòng)畫從當(dāng)前中心點(diǎn)平移到倫敦,動(dòng)畫過(guò)程2秒

onClick('pan-to-london', function() {
    view.animate({
        center: london,
        duration: 2000
    });
});
  • 自定義動(dòng)畫

easing可以自定義過(guò)渡效果函數(shù),返回值為0-1之間的小數(shù),代表起點(diǎn)到終點(diǎn)的變化進(jìn)度。下面的例子先定義了一個(gè)彈跳動(dòng)畫函數(shù),并使用該函數(shù)讓地圖以彈跳動(dòng)畫從當(dāng)前中心點(diǎn)平移到倫敦,動(dòng)畫過(guò)程2秒

function elastic(t) {
    return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1;
}

onClick('elastic-to-moscow', function() {
    view.animate({
        center: moscow,
        duration: 2000,
        easing: elastic
    });
});
  • 綜合應(yīng)用1

下面的例子展示了地圖從當(dāng)前中心點(diǎn)旋轉(zhuǎn)、平移到羅馬,前半程為入場(chǎng)動(dòng)畫,后半程為出場(chǎng)動(dòng)畫

onClick('spin-to-rome', function() {
    var center = view.getCenter();
    view.animate({
        center: [
            center[0] + (rome[0] - center[0]) / 2,
            center[1] + (rome[1] - center[1]) / 2
        ],
        rotation: Math.PI,
        easing: ol.easing.easeIn
    }, {
        center: rome,
        rotation: 2 * Math.PI,
        easing: ol.easing.easeOut
    });
});
  • 并發(fā)執(zhí)行

如果給一個(gè)過(guò)程設(shè)置了多個(gè)動(dòng)畫,他們都是并行執(zhí)行的。下面的動(dòng)畫類似于一只鳥的視角,從當(dāng)前中心點(diǎn)移動(dòng)到另一個(gè)中心點(diǎn)(動(dòng)畫1),并且前半程縮小視角、后半程回到原視角(動(dòng)畫2)。

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: location,
        duration: duration
    }, callback);
    view.animate({
        zoom: zoom - 1,
        duration: duration / 2
    }, {
        zoom: zoom,
        duration: duration / 2
    }, callback);
}

onClick('fly-to-bern', function() {
    flyTo(bern, function() {});
});
  • 綜合應(yīng)用2

下面的例子使用上面創(chuàng)建的“鳥視角飛躍函數(shù)”,在多個(gè)城市之間跳躍

function tour() {
    var locations = [london, bern, rome, moscow, istanbul];
    var index = -1;

    function next(more) {
        if (more) {
            ++index;
            if (index < locations.length) {
                var delay = index === 0 ? 0 : 750;
                setTimeout(function() {
                    flyTo(locations[index], next);
                }, delay);
            } else {
                alert('Tour complete');
            }
        } else {
            alert('Tour cancelled');
        }
    }
    next(true);
}

onClick('tour', tour);

本節(jié)測(cè)試用例的界面如下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容