Interactive Map InteractiveMap
  • July 24, 2025

Interactive Map

InteractiveMap


A Library to use SVG Based Maps interactively in SwiftUI.

  • Works only with .svg based maps
  • Allows you to modify all the provinces in the map with the attributes that SwiftUI’s Shape provides
  • Drag, drop and animate the provinces, as well as the map itself.

Note! SVG Parsing is not yet in its final form, so some SVGs may not be parsed correctly. But as far as I can see almost every map is drawn correctly. You can see the maps I tried in the Maps section.

Maps are taken from FSInteractiveMap Repository

Installation


 

Requires iOS 13+

InteractiveMap currently can only be installed through the Swift Package Manager

Swift Package Manager
Add the Package URL:
https://github.com/GrandSir/InteractiveMap

Examples & ShowCase


3d-map

Creepy Map

creepy)

mihmandar

Usage


SwiftUI


To draw your svg map in SwiftUI, use InteractiveMap with a closure taking PathData as the parameter.

InteractiveMap uses InteractiveShapes to draw all the paths defined in SVG. But it needs to know which Path will be drawn, that is, InteractiveMap { pathData in } works just like ForEach { index in } and returns an iterable closure returning PathData as parameter, which contains all the information about Paths defined inside svg.

import SwiftUI
import InteractiveMap

struct ContentView: View {
var body: some View {
InteractiveMap(svgName: “tr”) { pathData in // or just use $0
InteractiveShape(pathData)
.initWithAttributes()
}
}
}

InteractiveMap resizes itself to the assigned frame, takes all available space by default, and resizes itself responsively on device rotations.

Default Map

Customization


Instead of using default attributes, you can define your own attributes as well.

InteractiveMap(svgName: “tr”) {
InteractiveShape($0)
.initWithAttributes(.init(strokeWidth: 2, strokeColor: .red, background: Color(white: 0.2)))
}

Custom Attributes Map

Advanced Customization


Even though .initWithAttributes saves time for simple customization, it is neither highly customizable nor editable.

Since InteractiveShape is a Shape, you can use any methods with InteractiveShape that you can use with Shape.

InteractiveMap(svgName: “tr”) {
InteractiveShape($0)
.stroke(Color.cyan)
.shadow(color: .cyan, radius: 3, x: 0, y: 0)
.background(InteractiveShape($0).fill(Color(white: 0.15)))
}

Shadow Map

Handling Clicks

PathData is a Struct that contains all the information about all the paths, in our map example, they are districts and provinces.

It has 5 variables inside it. idpath and nameboundingBox and svgBounds

id is the Unique Identifier that’s being parsed directly from SVG

Most of the Map SVG’s (NOT ALL!) has the id attribute in all in their <path> element like this:

<path ... id="<id>", name="<name>">

MapParser, defined in MapParser.swift parses that element and stores them in PathData struct.

If there is not any id attribute in path, MapParser automatically creates an UUID String.

But if you’re going to store that id in somewhere, be aware that UUID String is automaticaly regenerated every time InteractiveMap is being drawed.

import SwiftUI
import InteractiveMap

struct ContentView: View {
@State private var clickedPath = PathData()
var body: some View {
VStack {
Text(clickedPath.name.isEmpty ? “” : “\(clickedPath.name) is clicked!” )
.font(.largeTitle)
.padding(.bottom, 15)

InteractiveMap(svgName: “tr”) { pathData in // is a PathData
InteractiveShape(pathData)
.stroke(clickedPath == pathData ? .cyan : .red, lineWidth: 1)
.shadow(color: clickedPath == pathData ? .cyan : .red, radius: 3)
.shadow(color: clickedPath == pathData ? .cyan : .clear , radius: 3) // to increase the glow amount
.background(InteractiveShape(pathData).fill(Color(white: 0.15))) // filling the shapes
.shadow(color: clickedPath == pathData ? .black : .clear , radius: 5, y: 1) // for depth

.onTapGesture {
clickedPath = pathData
}
.zIndex(clickedPath == pathData ? 2 : 1) // this is REQUIRED because InteractiveShapes overlap, resulting in an ugly appearance
.animation(.easeInOut(duration: 0.3), value: clickedPath)
}
}
}
}

clickedPath == pathData basically compares the id’s of the PathDatas.

clickable-map

GitHub


View Github

YOU MIGHT ALSO LIKE...
🧭 NavigationKit

NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Using Swift Package Manager, add ...

swiftui-navigation-stack

An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation. NavigationStack Installation ...

Stinsen

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it ...

SwiftUI Router

With SwiftUI Router you can power your SwiftUI app with path-based routing. By utilizing a path-based system, navigation in your app becomes ...

FlowStacks

This package takes SwiftUI's familiar and powerful NavigationStack API and gives it superpowers, allowing you to use the same API not just ...