Multi-Line Editing in edittrack: Work with Multiple Routes Simultaneously
Source: Dev.to
Planning Complex Routes
Planning complex routes often requires more than a single track. Whether you’re mapping a multi‑day trek, comparing alternative paths, or managing a network of interconnected trails, keeping all your routes in one workspace lets you see the full picture and maintain context while editing each part independently.
Starting with version 2.0‑beta, edittrack introduces multi‑line editing – the ability to create, edit, and manage multiple independent tracks within the same TrackManager. This post walks through the feature, its real‑world applications, and how to work with it.
What is Multi‑Line Editing?
Multi‑line editing lets you work with multiple independent line strings—called “parts”—in a single edittrack workspace. Each part is a complete track with its own:
- control points
- segments
- POIs
- routing configuration
You can:
- Create as many parts as you need
- Switch between parts to edit them individually
- See all parts simultaneously for context
- Style active and inactive parts differently for visual clarity
- Delete parts you no longer need
When you draw, move points, or add POIs, only the currently active part is affected. Other parts remain untouched, letting you refine one route without disrupting others.
Real‑World Use Cases
| Use Case | How Parts Help |
|---|---|
| Break a long journey into daily segments | Each day becomes its own part, so you can edit Day 3 without accidentally moving points from Day 1. All days stay visible on the map, giving you a sense of the full itinerary while you tweak individual stages. |
| Present options to clients or collaborators | Draw multiple variations side‑by‑side: • Scenic route vs. fastest route • Technical mountain‑bike trail vs. beginner‑friendly path • Main highway vs. scenic backroads Compare distances, elevation profiles, and surface types across alternatives before committing to one. |
| Build interconnected trail systems | A main route with optional side trips: • Primary hiking trail with viewpoint spurs • Different starting points converging at a common destination • Loop routes with shortcut options Each branch is its own part, making it easy to modify without tangling the entire network. |
| Separate parts by travel mode | Example: • Walk to the trailhead (part 0) • Bike the main trail (part 1) • Drive home (part 2) Or: • Approach routes vs. main climbing routes • Paved access roads vs. off‑road trails Each part can use a different routing profile or snapping configuration if needed. |
| Compare original vs. optimized routes | Keep the original route as part 0, then create part 1 for an optimized version. Compare them directly on the map. If the experiment doesn’t work, simply delete the new part or switch back to the original. |
Getting Started
If you’re familiar with edittrack from the first blog post, working with multiple parts builds naturally on what you already know. The key difference: instead of managing one track, you now manage multiple parts and switch between them.
Create a New Part
// Assuming you already have a TrackManager instance
const partIndex = trackManager.createNewPart();
// Returns the index (0, 1, 2, …) and automatically switches to that part
- The new part becomes the active part, and you can start drawing on it immediately.
- The first part you create is always part 0.
Switch to a Different Part
trackManager.workOnPart(1); // Switch to part 1
After switching, all drawing, point manipulation, and POI operations affect only that part.
Query the Active Part
const currentPart = trackManager.activePart();
console.log(`Editing part ${currentPart}`);
Get the Number of Parts
const total = trackManager.partsCount();
Delete a Part
trackManager.deletePart(2); // Remove part 2
- Deleting a part removes all its features (control points, segments, POIs) and renumbers subsequent parts to maintain a sequential index.
- If you delete the active part, edittrack automatically switches to another available part.
Drag‑to‑Switch Behavior
By default, edittrack lets you grab features from any part and automatically switches to that part when you start dragging. This makes quick edits intuitive: just grab a point from part 2, and edittrack switches context so you can move it.
To disable this behavior (e.g., to prevent accidental edits to inactive parts):
trackManager.switchPartOnDrag = false;
With switchPartOnDrag set to false, dragging features from inactive parts is blocked entirely, enforcing strict isolation between parts.
Accessing Data
The familiar methods—getSegments(), getControlPoints(), and getPOIs()—return data only from the currently active part.
If you need data from all parts at once, use the “all” variants:
const allSegments = trackManager.getAllSegments(); // Feature[][]
const allControlPoints = trackManager.getAllControlPoints(); // Feature[][]
const allPOIs = trackManager.getAllPOIs(); // Feature[][]
Each returns a nested array: allSegments[0] contains segments from part 0, allSegments[1] from part 1, and so on.
Iterate Over Parts with a Generator
for (const { index, trackData } of trackManager.partsGenerator()) {
console.log(`Part ${index} has ${trackData.segments.length} segments`);
// Process trackData.segments, trackData.controlPoints, trackData.pois
}
- The generator automatically restores the original active part when the loop completes, so you don’t have to track state manually.
Undo / Redo
Undo and redo now track both features and the active part. When you undo, edittrack restores not just the previous geometry and points, but also which part you were editing:
await trackManager.undo();
await trackManager.redo();
This means you can switch parts, make edits, switch again, and undo your way back through the entire sequence—edittrack remembers the active part at each step.
Styling Active vs. Inactive Parts
To help users distinguish between parts, edittrack sets an active property on every feature. This boolean indicates whether the feature belongs to the currently active part. You can use it in your style definitions:
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"]
};
- Active parts appear bolder and brighter, while inactive parts are muted, giving users clear visual feedback.
Summary
Multi‑line editing in edittrack version 2.0‑beta gives you the power to:
- Create unlimited independent parts within a single workspace.
- Switch seamlessly between parts for focused editing.
- Visualize all parts together while keeping each isolated.
- Compare, experiment, and iterate on multiple route options without losing context.
Give it a try, and let us know how it transforms your routing workflows!
Styling Example
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",
};
Similarly, control points can use conditional styling:
const controlPointStyle = {
"circle-fill-color": [
"case",
["==", ["get", "active"], false],
"#0071ec80", // Semi‑transparent blue for inactive
"#0071ecff" // Opaque blue for active
],
};
The part property stores the numeric index (0, 1, 2, …) of each feature’s part. Displaying this number as a label on the map helps users keep track of which part is which, especially when working with many parts.
Live Demo Controls
- Add a new line string – creates a new empty part
- Change active line string – cycles through existing parts
- Delete active line string – removes the currently active part
How to Experiment
- Draw a route on part 0 by clicking points on the map.
- Click “Add a new line string” to create part 1.
- Draw a second route – notice the first route becomes semi‑transparent.
- Click “Change active line string” to switch back to part 0 and modify it.
- Try dragging points from inactive parts to see automatic switching in action.
The demo uses the conditional styling shown above, so you’ll see a clear visual distinction between active and inactive parts.
Resources
- Docs:
- Demos: simple, schm
- Source:
- npm:
@geoblocks/edittrack
License
BSD‑3‑Clause