Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

MorphingView

A lightweight SwiftUI framework for creating fluid morphing transitions between two pieces of content.

MorphingView combines SwiftUI view composition, an animatable blur progression, compositing, and a SwiftUI stitchable Metal shader to produce a smooth visual transformation between a source view and a destination view.

Requirements

  • iOS 18.0+
  • Swift 6.4+
  • Xcode 27+
  • SwiftUI
  • Metal / SwiftUI shader support

Features

  • SwiftUI-native API
  • Two public APIs for different usage styles
  • Animatable morphing progress
  • Configurable blur radius
  • Custom stitchable Metal shader for alpha thresholding
  • Distributed as a prebuilt XCFramework
  • Swift Package Manager binary target support

Installation

Swift Package Manager

MorphingView is distributed as a binary Swift Package.

Add the package dependency to your project using the repository URL:

https://github.com/thakur-vijay/MorphingView.git

The package exposes the MorphingView library product.

After adding the dependency:

import MorphingView

Usage

MorphingView provides two public APIs.

1. MorphingView

Use this API when you want to explicitly provide both the source and destination views.

import SwiftUI
import MorphingView

struct ExampleView: View {
    @State private var isActive = false

    var body: some View {
        MorphingView(
            blurRadius: 8,
            toggle: isActive
        ) {
            Image(systemName: "heart")
                .font(.system(size: 48))
        } to: {
            Image(systemName: "heart.fill")
                .font(.system(size: 48))
        }
        .onTapGesture {
            withAnimation(.easeInOut(duration: 0.4)) {
                isActive.toggle()
            }
        }
    }
}

When toggle is false, the from content is displayed. When toggle is true, the to content is displayed.

2. View Modifier

When the current view should be the source of the morph, the modifier API is more concise.

import SwiftUI
import MorphingView

struct ExampleView: View {
    @State private var isLiked = false

    var body: some View {
        Image(systemName: "heart")
            .font(.system(size: 48))
            .morphing(
                blurRadius: 8,
                toggle: isLiked
            ) {
                Image(systemName: "heart.fill")
                    .font(.system(size: 48))
            }
            .onTapGesture {
                withAnimation(.easeInOut(duration: 0.4)) {
                    isLiked.toggle()
                }
            }
    }
}

The modifier API follows this model:

self → from
 to  → destination

Animation

MorphingView does not own an animation. The transition is driven by SwiftUI's animation system.

For example:

withAnimation(.easeInOut(duration: 0.4)) {
    isActive.toggle()
}

This separation keeps the component composable with SwiftUI animation APIs.

Recommended Usage

Use a moderate blur radius and let the animation duration determine the character of the transition.

For example:

.morphing(
    blurRadius: 8,
    toggle: state
) {
    DestinationView()
}

The appropriate blur value depends on the size and visual complexity of the content. Higher values create a softer, more diffuse transition but can also increase rendering cost and reduce visual clarity.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages