edittrack에서 다중 라인 편집: 여러 경로를 동시에 작업
Source: Dev.to
복잡한 경로 계획
복잡한 경로를 계획할 때는 하나의 트랙만으로는 충분하지 않은 경우가 많습니다. 며칠에 걸친 트레킹을 설계하든, 대체 경로를 비교하든, 혹은 서로 연결된 여러 트레일 네트워크를 관리하든, 모든 경로를 하나의 작업 공간에 두면 전체 그림을 한눈에 파악할 수 있고, 각 부분을 독립적으로 편집하면서도 컨텍스트를 유지할 수 있습니다.
버전 2.0‑beta부터 edittrack은 다중 라인 편집을 도입했습니다 – 동일한 TrackManager 안에서 여러 개의 독립적인 트랙을 생성·편집·관리할 수 있는 기능입니다. 이 게시물에서는 이 기능의 실제 활용 사례와 사용 방법을 단계별로 살펴봅니다.
멀티라인 편집이란?
멀티라인 편집을 사용하면 단일 edittrack 작업 공간에서 “parts”(파트) 라고 부르는 여러 개의 독립적인 라인 문자열을 다룰 수 있습니다. 각 파트는 자체적인 다음 요소를 가진 완전한 트랙입니다:
- 제어점
- 구간
- POI
- 라우팅 구성
가능한 작업:
- Create 필요에 따라 원하는 만큼 파트를 생성
- Switch 파트 간 전환하여 개별 편집
- See 컨텍스트를 위해 모든 파트를 동시에 보기
- Style 시각적 명확성을 위해 활성 파트와 비활성 파트를 다르게 스타일링
- Delete 더 이상 필요 없는 파트 삭제
그리기, 포인트 이동, POI 추가 등을 할 때는 현재 활성 파트만 영향을 받습니다. 다른 파트는 그대로 유지되어 하나의 경로를 다듬어도 다른 경로에 영향을 주지 않습니다.
실제 활용 사례
| 사용 사례 | 파트가 도움이 되는 방법 |
|---|---|
| 긴 여정을 일일 구간으로 나누기 | 각 날이 별도의 파트가 되므로 Day 3을 편집할 때 Day 1의 포인트가 실수로 이동하지 않게 됩니다. 모든 날이 지도에 표시된 채로 전체 일정 감각을 유지하면서 개별 구간을 조정할 수 있습니다. |
| 클라이언트나 협업자에게 옵션 제시 | 여러 변형을 나란히 그리기: • 경치 좋은 루트 vs. 가장 빠른 루트 • 기술적인 산악 자전거 트레일 vs. 초보자 친화 경로 • 주요 고속도로 vs. 경치 좋은 시골길 대안을 선택하기 전에 거리, 고도 프로필, 표면 유형을 비교합니다. |
| 상호 연결된 트레일 시스템 구축 | 선택 가능한 사이드 트립이 포함된 주요 경로: • 전망대가 있는 주요 하이킹 트레일 • 공통 목적지로 모이는 다양한 시작점 • 지름길 옵션이 있는 루프 경로 각 분기는 별도의 파트이므로 전체 네트워크를 복잡하게 만들지 않고도 쉽게 수정할 수 있습니다. |
| 여행 방식별 파트 구분 | 예시: • 트레일헤드까지 도보 (파트 0) • 주요 트레일을 자전거로 (파트 1) • 집까지 운전 (파트 2) 또는: • 접근 경로 vs. 주요 등산 경로 • 포장된 접근 도로 vs. 오프로드 트레일 필요에 따라 각 파트는 다른 라우팅 프로필이나 스냅핑 설정을 사용할 수 있습니다. |
| 원본과 최적화된 경로 비교 | 원본 경로를 파트 0으로 유지하고, 최적화된 버전을 위해 파트 1을 생성합니다. 지도에서 직접 비교합니다. 실험이 실패하면 새 파트를 삭제하거나 원본으로 되돌리면 됩니다. |
Source: …
시작하기
첫 번째 블로그 포스트에서 edittrack을 사용해 본 적이 있다면, 여러 파트를 다루는 것은 이미 알고 있는 내용에 자연스럽게 이어집니다. 핵심 차이점은 하나의 트랙을 관리하던 것을 이제는 여러 파트를 관리하고 그 사이를 전환한다는 점입니다.
새 파트 만들기
// Assuming you already have a TrackManager instance
const partIndex = trackManager.createNewPart();
// Returns the index (0, 1, 2, …) and automatically switches to that part
- 새 파트는 활성 파트가 되며, 바로 그 위에 그리기를 시작할 수 있습니다.
- 처음 만든 파트는 항상 파트 0입니다.
다른 파트로 전환하기
trackManager.workOnPart(1); // Switch to part 1
전환 후에는 모든 그리기, 포인트 조작, POI 작업이 해당 파트에만 영향을 미칩니다.
활성 파트 조회하기
const currentPart = trackManager.activePart();
console.log(`Editing part ${currentPart}`);
파트 수 확인하기
const total = trackManager.partsCount();
파트 삭제하기
trackManager.deletePart(2); // Remove part 2
- 파트를 삭제하면 해당 파트의 모든 피처(제어점, 세그먼트, POI)가 제거되고 후속 파트들의 인덱스가 순차적으로 재배열됩니다.
- 활성 파트를 삭제하면 edittrack이 자동으로 다른 사용 가능한 파트로 전환합니다.
Drag‑to‑Switch Behavior
기본적으로 edittrack은 어떤 파트에서든 피처를 잡을 수 있게 해 주며, 드래그를 시작하면 자동으로 해당 파트로 전환합니다. 이렇게 하면 빠른 편집이 직관적입니다: 파트 2의 점을 잡기만 하면 edittrack이 컨텍스트를 전환해 이동할 수 있게 합니다.
이 동작을 비활성화하려면 (예: 비활성 파트에 대한 실수 편집을 방지하려면):
trackManager.switchPartOnDrag = false;
switchPartOnDrag를 false로 설정하면, 비활성 파트에서 피처를 드래그하는 것이 완전히 차단되어 파트 간의 엄격한 격리를 보장합니다.
데이터 접근
익숙한 메서드인 getSegments(), getControlPoints(), getPOIs()는 현재 활성 파트에서만 데이터를 반환합니다.
한 번에 모든 파트의 데이터가 필요하다면, “all” 변형을 사용하세요:
const allSegments = trackManager.getAllSegments(); // Feature[][]
const allControlPoints = trackManager.getAllControlPoints(); // Feature[][]
const allPOIs = trackManager.getAllPOIs(); // Feature[][]
각 메서드는 중첩 배열을 반환합니다: allSegments[0]은 파트 0의 세그먼트를, allSegments[1]은 파트 1의 세그먼트를 포함하며, 이와 같이 이어집니다.
제너레이터를 사용해 파트 순회
for (const { index, trackData } of trackManager.partsGenerator()) {
console.log(`Part ${index} has ${trackData.segments.length} segments`);
// Process trackData.segments, trackData.controlPoints, trackData.pois
}
- 제너레이터는 루프가 끝나면 자동으로 원래의 활성 파트를 복원하므로, 상태를 수동으로 추적할 필요가 없습니다.
실행 취소 / 다시 실행
실행 취소와 다시 실행은 이제 두 기능과 현재 활성 파트를 모두 추적합니다. 실행 취소를 하면 edittrack은 이전 기하학 및 포인트뿐만 아니라 편집 중이던 파트도 복원합니다:
await trackManager.undo();
await trackManager.redo();
즉, 파트를 전환하고 편집을 수행한 뒤 다시 전환하고, 전체 순서를 따라 실행 취소를 하면—edittrack은 각 단계에서 활성 파트를 기억합니다.
활성 파트와 비활성 파트 스타일링
사용자가 파트를 구분하기 쉽도록 edittrack은 모든 피처에 active 속성을 설정합니다. 이 불리언은 해당 피처가 현재 활성 파트에 속하는지를 나타냅니다. 스타일 정의에 이를 사용할 수 있습니다:
const trackLineStyle = {
"stroke-width": ["case", ["==", ["get", "active"], true], 4, 2],
"stroke-color": ["case", ["==", ["get", "active"], true], "#ff6600", "#999999"]
};
const pointStyle = {
"icon-size": ["case", ["==", ["get", "active"], true], 1.2, 0.8],
"icon-color": ["case", ["==", ["get", "active"], true], "#ff6600", "#666666"]
};
- 활성 파트는 두껍게 그리고 밝게 표시되고, 비활성 파트는 색이 흐려져 사용자가 명확한 시각적 피드백을 얻을 수 있습니다.
요약
Multi‑line editing in edittrack version 2.0‑beta gives you the power to:
- Create 단일 작업 공간 내에서 무제한 독립 파트를 생성합니다.
- Switch 파트 간에 원활하게 전환하여 집중 편집을 할 수 있습니다.
- Visualize 각 파트를 격리된 상태로 유지하면서 모두 시각화합니다.
- Compare, experiment, iterate 여러 경로 옵션을 비교·실험·반복하면서 컨텍스트를 잃지 않습니다.
한번 사용해 보시고, 라우팅 워크플로우가 어떻게 변하는지 알려 주세요!
스타일링 예시
const lineStyle = {
"line-width": 6,
"stroke-color": [
"case",
["==", ["get", "active"], false],
"#00883c80", // Semi‑transparent green for inactive parts
"#00883cff" // Opaque green for active parts
],
"text-value": ["concat", "", ["get", "part"]], // Display part number as text
"text-fill-color": "#fff",
};
마찬가지로, 제어점에도 조건부 스타일링을 적용할 수 있습니다:
const controlPointStyle = {
"circle-fill-color": [
"case",
["==", ["get", "active"], false],
"#0071ec80", // Semi‑transparent blue for inactive
"#0071ecff" // Opaque blue for active
],
};
part 속성은 각 피처의 파트 번호(0, 1, 2, …)를 저장합니다. 이 번호를 지도에 라벨로 표시하면 많은 파트를 다룰 때 어떤 파트가 어느 것인지 사용자가 쉽게 파악할 수 있습니다.
라이브 데모 컨트롤
- 새 라인 문자열 추가 – 새로운 빈 파트를 생성합니다
- 활성 라인 문자열 변경 – 기존 파트를 순환합니다
- 활성 라인 문자열 삭제 – 현재 활성 파트를 제거합니다
실험 방법
- 파트 0에 경로를 그리세요 지도에 포인트를 클릭하여.
- “Add a new line string”(새 라인 문자열 추가) 를 클릭하여 파트 1을 만듭니다.
- 두 번째 경로를 그리세요 – 첫 번째 경로가 반투명해지는 것을 확인하세요.
- “Change active line string”(활성 라인 문자열 변경) 을 클릭하여 파트 0으로 돌아가 수정합니다.
- 비활성 파트의 포인트를 드래그해 자동 전환이 작동하는 것을 확인해 보세요.
데모는 위에 표시된 조건부 스타일링을 사용하므로, 활성 파트와 비활성 파트 사이의 시각적 구분을 명확히 볼 수 있습니다.
리소스
- 문서:
- 데모: simple, schm
- Source:
- npm:
@geoblocks/edittrack
라이선스
BSD‑3‑Clause