Code Monkey home page Code Monkey logo

swiftuimap's Introduction

SwiftUIMap

SwiftUIMap is the best UIKit wrapper for MapKit!

Installation

Swift Package Manager

Currently, we only support set annotations, but are working on a user addable marker map.

Requirements

  • iOS 14, macOS 10.16, tvOS 14, or watchOS 67
  • Swift 5.5+
  • Xcode 13.0+

Installation

The preferred way of installing SwiftUIMap is via the Swift Package Manager.

  1. In Xcode, open your project and navigate to File โ†’ Add Packages...
  2. Paste the repository URL (https://github.com/Mcrich23/SwiftUIMap) and click Next.
  3. For Rules, select Up To Next Major Version (With base version set to 1.1.0).
  4. Click Finish.
  5. Check Mcrich23-Toolkit
  6. Click Add To Project

Usage

Note: To use a map from SwiftUIMap, you need to import MapKit

AnnotationMapView

ExistingMapView (
    zoom: 0.4, // Starting Zoom of Map (Range: 0-1, Lower is closer in)
    address: "Seattle, Wa", // Starting address in the Center of the Map (use this or coordinates)
    points: [
        Annotations(
            title: "Townhall", // Top line on map
            subtitle: "Newly Remodeled", // Underneath top line when clicked
            location: .address("1119 8th Ave, Seattle, WA, 98101, United States"), // Location for point
            glyphImage: .defaultIcon, // Glyph icon on map point
            markerTintColor: .red, // Marker background
            glyphTintColor: .white, // Glyph icon color
            displayPriority: .required // How markers are shown
        )
    ],
    isUserLocationVisible: $isUserLocationVisible, // Binding for if isUserLocationVisible
    selected: { Title, Subtitle, Address, isCluster in // Action When Marker is Selected (Returns title, subtitle, and address in annotation along with if it's in a cluster)
        print("tapped \(Address)")
    }, deselected: { // Action When Marker is Deselceted
        print("deselected annotation")
    }, advancedModifiers: { // Full access to MKMapView modifiers
        map.alpha = 0.4
    }
)

MutableMapView

MutableMapView (
    zoom: 0.4, // Starting Zoom of Map (Range: 0-1, Lower is closer in)
    address: "Seattle, Wa", // Starting address in the Center of the Map (use this or coordinates)
    isFirstResponder: $isFirstResponder // Binding for if isFirstResponder
)

Modifiers

...
    .pointsOfInterest(.excludingAll) // Filter Points of Interest (exclude or include all)
    .pointOfInterestCategories(include: [.atm]) // Filter Points of Interest to only include things in an array
    .pointOfInterestCategories(exclude: [.airport]) // Filter Points of Interest to include everything except things in an array
    .showCompass(false) // Show Compass (true or false)
    .showScale(false) // Show Scale (true or false)
    .showTraffic(false) // Show Traffic (true or false)
    .showBuildings(false) // Show Buildings (true or false)
    .mapType(.satellite) // Different types of map (Standard, MutedStandard, Hybrid, HybridFlyover, Satellite, SatelliteFlyover)
    .camera(MKMapCamera(lookingAtCenter: loc, fromDistance: .pi, pitch: 4, heading: .pi)) // Customize the camera angle
    .cameraBoundary(MKMapView.CameraBoundary(coordinateRegion: MKCoordinateRegion(center: loc, span: MKCoordinateSpan(latitudeDelta: 4, longitudeDelta: 4)))) // Customize the camera boundary
    .cameraZoomRange(MKMapView.CameraZoomRange(minCenterCoordinateDistance: CLLocationDistance(600))) // Customize the zoom range (minCenterCoordinateDistance and maxCenterCoordinateDistance)
    .isPitchEnabled(true) // Enable or disable the use of pitch
    .isUserInteractionEnabled(true) // Enable or disable interaction
    .isZoomEnabled(true) // Enable or disable the use of zoom
    .isRotateEnabled(true) // Enable or disable the use of rotation
    .isScrollEnabled(true) // Enable or disable the use of scroll
    .isMultipleTouchEnabled(true) // Enable or disable the use of multi-touch
    .userTrackingMode(.none) // Sets the mode for user tracking (must have permission to track user)

MapSearchView

MapSearchView(resultTypes: .address, pointOfInterestFilter: .init(including: [.restaurant]), onSelect: { address in //Address passed back
    zoom = 0.2 // Zooms out
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(650), execute: { // Wait to go to the new place
        self.address = address // Change central address
    })
})

defaultCameraAngle

SwiftUIMap.defaultCameraAngle( // Get Default Camera Angle
    location: CLLocationCoordinate2D( // Center coordinates
        latitude: lat, // Latitude for center coordinate
        longitude: long // Longitude for center coordinate
    ), 
    zoom: zoom // How far zoomed in the camera is
)

License

ScrollKit is available under the MIT license. See the LICENSE file for more info.

swiftuimap's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

anil291987

swiftuimap's Issues

Map Drag, Zoom, Rotate Freezes Map

Describe the bug
It seems that updating the map with any gesture causes the map to simply freeze, rather than panning and zooming. The same thing happens whenever I tap on an Annotation

To Reproduce
Steps to reproduce the behavior:

  1. Launch on Previews or Simulator at Map
  2. Attempt to interact

Expected behavior
It should allow gestures

Versions (please complete the following information):

  • Running OS: iOS 16
  • Xcode: 14.3
  • Development OS: Ventura 13.4

Screenshots
Shows loading the map, using the code below, and that I can't interact with it.
Simulator Screen Recording - iPhone 14 Pro Max - 2023-06-23 at 14 27 39

Additional context

struct MapView: View {
    @EnvironmentObject var appConfig: AppConfig
    
    @State var zoom: Double = 1.0
    @State var coordinates: LocationCoordinate
    @State var points: [Annotations]
    @State var isUserLocationVisible = false

    var body: some View {
        AnnotationMapView(
            zoom: $zoom, // Starting Zoom of Map (Range: 0-1, Lower is closer in)
            coordinates: $coordinates, // Starting address in the Center of the Map (use this or coordinates)
            points: $points,
            isUserLocationVisible: $isUserLocationVisible, // Binding for if isUserLocationVisible
            selected: { Title, Subtitle, Address, isCluster in // Action When Marker is Selected (Returns title, subtitle, and address in annotation along with if it's in a cluster)
                print("tapped \(Address)")
            }, deselected: { // Action When Marker is Deselceted
                print("deselected annotation")
            }
        )
        .showCompass(true)
        .pointsOfInterest(.excludingAll)
        .mapType(.standard)
        .isMultipleTouchEnabled(true)
        .isUserInteractionEnabled(true)
        .isScrollEnabled(true)
        .isRotateEnabled(true)
        .isZoomEnabled(true)
        .camera(MKMapCamera(lookingAtCenter: coordinates, fromDistance: zoom*999999, pitch: 0, heading: 0))
        .cameraBoundary(MKMapView.CameraBoundary(coordinateRegion: MKCoordinateRegion(center: coordinates, span: MKCoordinateSpan(latitudeDelta: 4, longitudeDelta: 4))))
        .cameraZoomRange(MKMapView.CameraZoomRange(minCenterCoordinateDistance: CLLocationDistance(600)))
    }
    
    init(pois: [LocationDetail]) {
        self.coordinates = RegionCalculator.calculateRegion(from: pois).center
        self.points = pois.map {
            Annotations(title: $0.locationName,
                        subtitle: $0.locationDescription,
                        location: .coordinates($0.coordinate),
                        glyphImage: .defaultIcon,
                        markerTintColor: .blue,
                        glyphTintColor: .red,
                        displayPriority: .defaultHigh)
        }
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView(pois: appConfig.poiLocations ?? [])
            .environmentObject(appConfig)
    }
}

class RegionCalculator {
    static func calculateRegion(from pois: [LocationDetail]) -> MKCoordinateRegion {
        guard !pois.isEmpty else {
            return MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0, longitude: 0), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
        }
        
        var totalLat = 0.0
        var totalLong = 0.0
        
        for poi in pois {
            totalLat += poi.coordinate.latitude
            totalLong += poi.coordinate.longitude
        }
        
        let avgLat = totalLat / Double(pois.count)
        let avgLong = totalLong / Double(pois.count)
        
        return MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: avgLat, longitude: avgLong), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
    }
}

Request

It's entirely possible that I have miffed the implementation completely, if so please let me know and I'll attempt to correct it. Also, is it possible to utilize a custom SwiftUI view in place of the Annotation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.