Animate Line
routogl 지도에 애니메이션 효과가 적용된 라인을 생성/삭제하는 예제입니다.
const map = new routogl.Map({
container: 'map', // container ID
style: routogl.RoutoStyle.LIGHT,
center: [127.0430272, 37.516700], // 초기 위치 [lng, lat]
zoom: 16, // 초기 줌 레벨
});
// 선형 GeoJSON 빈 Object 생성
const geojson = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': []
}
}
]
};
// 애니메이션 라인이 표시될 좌표 목록
const path = [
[127.0412063, 37.517635],
[127.0411937, 37.517670],
[127.0411810, 37.517705],
[127.0411684, 37.517740],
[127.0411558, 37.517775],
[127.0411431, 37.517810],
[127.0411489, 37.517844],
[127.0411686, 37.517875],
[127.0411884, 37.517907],
[127.0412082, 37.517938],
[127.0412399, 37.517953],
[127.0412766, 37.517959],
[127.0413132, 37.517966],
[127.0413499, 37.517973],
[127.0413866, 37.517980],
[127.0414232, 37.517987],
[127.0414599, 37.517994],
[127.0414966, 37.518001],
[127.0415332, 37.518008],
[127.0415699, 37.518015],
[127.0416066, 37.518022],
[127.0416432, 37.518028],
[127.0416799, 37.518035],
[127.0417166, 37.518042],
[127.0417532, 37.518049],
[127.0417899, 37.518056],
[127.0418266, 37.518063],
[127.0418632, 37.518070],
[127.0418999, 37.518077],
[127.0419366, 37.518084],
[127.0419732, 37.518091],
[127.0420099, 37.518097],
[127.0420466, 37.518104],
[127.0420832, 37.518111],
[127.0421199, 37.518118],
[127.0421566, 37.518125],
[127.0421932, 37.518132],
[127.0422299, 37.518139],
[127.0422666, 37.518146],
[127.0423032, 37.518153],
[127.0423399, 37.518160],
[127.0423766, 37.518166],
[127.0424132, 37.518173],
[127.0424499, 37.518180],
[127.0424866, 37.518187],
[127.0425232, 37.518194],
[127.0425599, 37.518201],
[127.0425966, 37.518208],
[127.0426332, 37.518215],
[127.0426699, 37.518222],
[127.0427066, 37.518229],
[127.0427432, 37.518235],
[127.0427799, 37.518242],
[127.0428166, 37.518249],
[127.0428532, 37.518256],
[127.0428899, 37.518263],
[127.0429266, 37.518270],
[127.0429632, 37.518277],
[127.0429999, 37.518284],
[127.0430366, 37.518291],
[127.0430732, 37.518298],
[127.0431099, 37.518304],
[127.0431466, 37.518311],
[127.0431832, 37.518318],
[127.0432199, 37.518325],
[127.0432566, 37.518332],
[127.0432934, 37.518337],
[127.0433307, 37.518339],
[127.0433679, 37.518341],
[127.0434052, 37.518343],
[127.0434424, 37.518345],
[127.0434797, 37.518347],
[127.0435112, 37.518333],
[127.0435386, 37.518308],
[127.0435660, 37.518283],
[127.0435934, 37.518257],
[127.0436038, 37.518222],
[127.0436136, 37.518186],
[127.0436235, 37.518150],
[127.0436333, 37.518114],
[127.0436431, 37.518078],
[127.0436529, 37.518042],
[127.0436627, 37.518006],
[127.0436726, 37.517970],
[127.0436824, 37.517934],
[127.0436922, 37.517898],
[127.0437020, 37.517862],
[127.0437119, 37.517826],
[127.0437217, 37.517790],
[127.0437315, 37.517754],
[127.0437413, 37.517718],
[127.0437511, 37.517682],
[127.0437610, 37.517646],
[127.0437708, 37.517610],
[127.0437806, 37.517574],
[127.0437904, 37.517538],
[127.0438002, 37.517502],
[127.0438101, 37.517466],
[127.0438199, 37.517430],
[127.0438297, 37.517394],
[127.0438395, 37.517358],
[127.0438494, 37.517322],
[127.0438592, 37.517286],
[127.0438690, 37.517250],
[127.0438788, 37.517214],
[127.0438886, 37.517178],
[127.0438985, 37.517142],
[127.0439083, 37.517106],
[127.0439181, 37.517070],
[127.0439279, 37.517034],
[127.0439377, 37.516998],
[127.0439476, 37.516962],
[127.0439574, 37.516926],
[127.0439672, 37.516890],
[127.0439770, 37.516854],
[127.0439869, 37.516818],
[127.0439967, 37.516782],
[127.0440065, 37.516746],
[127.0440163, 37.516710],
[127.0440261, 37.516674],
[127.0440360, 37.516638],
[127.0440458, 37.516602],
[127.0440556, 37.516566],
[127.0440654, 37.516530],
[127.0440752, 37.516494],
[127.0440851, 37.516458],
[127.0440949, 37.516422],
[127.0441047, 37.516386],
[127.0441145, 37.516350],
[127.0441244, 37.516314],
[127.0441342, 37.516278],
[127.0441440, 37.516242],
[127.0441538, 37.516206],
[127.0441636, 37.516170],
[127.0441735, 37.516134],
[127.0441833, 37.516098],
[127.0441931, 37.516062],
[127.0442029, 37.516026],
[127.0442128, 37.515990],
[127.0442226, 37.515954],
[127.0442324, 37.515918],
[127.0442422, 37.515882],
[127.0442520, 37.515846],
[127.0442619, 37.515810],
[127.0442717, 37.515774],
[127.0442815, 37.515738],
[127.0442787, 37.515709],
[127.0442432, 37.515698],
[127.0442077, 37.515686],
[127.0441722, 37.515675],
[127.0441367, 37.515663],
[127.0441012, 37.515652],
[127.0440657, 37.515640],
[127.0440302, 37.515629],
[127.0439947, 37.515617],
[127.0439592, 37.515606],
[127.0439237, 37.515594],
[127.0438882, 37.515583],
[127.0438527, 37.515571],
[127.0438172, 37.515560],
[127.0437817, 37.515548],
[127.0437462, 37.515537],
[127.0437107, 37.515525],
[127.0436752, 37.515514],
[127.0436397, 37.515502],
[127.0436031, 37.515495],
[127.0435665, 37.515488],
[127.0435299, 37.515481],
[127.0434933, 37.515474],
[127.0434567, 37.515466],
[127.0434200, 37.515459],
[127.0433834, 37.515452],
[127.0433468, 37.515445],
[127.0433102, 37.515438],
[127.0432736, 37.515430],
[127.0432370, 37.515423],
[127.0432004, 37.515416],
[127.0431638, 37.515409],
[127.0431272, 37.515402],
[127.0430906, 37.515394],
[127.0430539, 37.515387],
[127.0430173, 37.515380],
[127.0429807, 37.515373],
[127.0429441, 37.515366],
[127.0429075, 37.515359],
[127.0428709, 37.515351],
[127.0428343, 37.515344],
[127.0427977, 37.515337],
[127.0427611, 37.515330],
[127.0427245, 37.515323],
[127.0426878, 37.515315],
[127.0426512, 37.515308],
[127.0426146, 37.515301],
[127.0425780, 37.515294],
[127.0425414, 37.515287],
[127.0425048, 37.515279],
[127.0424682, 37.515272],
[127.0424316, 37.515265],
];
const speedFactor = 60; // 프레임 / 경도
let animation; // 애니메이션
let startTime = 0; // 시작 시간
let progress = 0; // 진행률 = 경과 시간 - 시작 시간
let resetTime = false;
const pauseButton = document.getElementById('pause');
map.on('load', () => {
map.addSource('line', {
'type': 'geojson',
'data': geojson
});
// add the line which will be modified in the animation
map.addLayer({
'id': 'line-animation',
'type': 'line',
'source': 'line',
'layout': {
'line-cap': 'round',
'line-join': 'round'
},
'paint': {
'line-color': '#ed6498',
'line-width': 5,
'line-opacity': 0.8
}
});
startTime = performance.now();
animateLine();
// '정지', '시작' 버튼의 클릭 이벤트
pauseButton.addEventListener('click', () => {
pauseButton.classList.toggle('pause');
if (pauseButton.classList.contains('pause')) {
cancelAnimationFrame(animation);
} else {
resetTime = true;
animateLine();
}
});
// 포커스를 잃거나 얻으면 애니메이션을 초기화
document.addEventListener('visibilitychange', () => {
resetTime = true;
});
// 애니메이션 라인
function animateLine(timestamp) {
if (resetTime) {
// 정지한 시점 부터 시작
startTime = performance.now() - progress;
resetTime = false;
} else {
progress = timestamp - startTime;
}
// 애니메이션이 종료되면 재시작 처리
if (progress > speedFactor * 200) {
startTime = timestamp;
geojson.features[0].geometry.coordinates = [];
} else {
// 진행에 따라 경로 좌표를 하나씩 추가하여 애니메이션 효과 표시
const index = Math.round(progress / speedFactor);
if(path[index]){
geojson.features[0].geometry.coordinates.push(path[index]);
}
map.getSource('line').setData(geojson);
}
animation = requestAnimationFrame(animateLine);
}
});
