WEB GL JS

웹 개발, 어플리케이션에서 활용될 수 있도록 Javascript로 제공되는 지도 플랫폼 입니다.

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);
  }
});