Multi-Line Editing in edittrack: Work with Multiple Routes Simultaneously

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 multi-line editing offers

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, and 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

Multi-day trips

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 remain visible on the map, giving you a sense of the full itinerary while you tweak individual stages.

Alternative routes

Present options to clients or collaborators by drawing 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.

Route networks

Build interconnected trail systems where a main route has optional side trips:

  • A 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.

Activity segments

Separate parts based on how you’ll travel:

  • Walk to the trailhead (part 0), bike the main trail (part 1), drive home (part 2)
  • Approach routes vs. main climbing routes
  • Paved access roads vs. off-road trails

Each part can use different routing profiles or snapping configurations if needed.

Version control and experimentation

Keep your 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.

Working with multiple parts: the API

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.

Creating new parts

Start with an existing TrackManager instance. Call createNewPart() to add a new empty part:

const partIndex = trackManager.createNewPart();
// Returns the index (0, 1, 2, etc.) and automatically switches to that part

The new part becomes the active part, and you can immediately start drawing on it. The first part you create is always part 0.

Switching between parts

To edit a different part, use workOnPart():

trackManager.workOnPart(1); // Switch to part 1

After switching, all drawing, point manipulation, and POI operations affect only that part. To check which part is currently active:

const currentPart = trackManager.activePart();
console.log(`Editing part ${currentPart}`);

Managing parts

Find out how many parts you have:

const total = trackManager.partsCount();

Delete a part you no longer need:

trackManager.deletePart(2); // Remove part 2

Deleting a part removes all its features—control points, segments, and POIs—and renumbers subsequent parts to maintain a sequential index. If you delete the active part, edittrack automatically switches to another available part.

Automatic switching on drag

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 this set to false, dragging features from inactive parts is blocked entirely, enforcing strict isolation between parts.

Getting data from all parts

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(); // Returns Feature[][]
const allControlPoints = trackManager.getAllControlPoints();
const allPOIs = trackManager.getAllPOIs();

Each of these returns a nested array: one sub-array per part. For example, allSegments[0] contains segments from part 0, allSegments[1] contains segments from part 1, and so on.

Iterating through parts

To process each part individually without manually switching back and forth, use the partsGenerator() method:

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.

History management

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 which part was active at each step.

Visual feedback and user experience

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 styles to make active parts stand out:

const trackLineStyle = {
  "stroke-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, etc.) 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.

Try it yourself

The live demo now includes three new 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

To experiment:

  1. Draw a route on part 0 by clicking points on the map
  2. Click “Add a new line string” to create part 1
  3. Draw a second route—notice the first route becomes semi-transparent
  4. Click “Change active line string” to switch back to part 0 and modify it
  5. Try dragging points from inactive parts to see automatic switching in action

The demo uses the conditional styling shown above, so you’ll see clear visual distinction between active and inactive parts.

License

BSD-3-Clause

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

BigQuery Sharing: An Underrated Data Exchange Platform You Should Know

Next Post

Answer engine optimization vs. traditional SEO: What marketers need to know

Related Posts