0

I have tried to find the Before-After slider effect for images in SwiftUI. But I cannot find any libraries or solutions. And finally I came up with below solution myself.

Hope this help someone!!

john raja
  • 509
  • 4
  • 8
  • What is the after-effects tag for and what does your question have to do with Adobe After Effects? – El Tomato Aug 01 '21 at 09:19
  • Actually I cannot find the appropriate tags (before-after or before_after). StackOverflow stays at least 1500 reputation needs to create a new tag. That's why I have added a related tags to the question. However I changed the tags for the question. – john raja Aug 02 '21 at 06:35

1 Answers1

1

I have added background color for images for to make differ if there is no images.

import SwiftUI

struct ContentView: View {

@State private var location: CGPoint = CGPoint(x: 0, y: 0)
@State private var maskWidth: CGFloat = 0.0

@State var startPoint: CGFloat = 0
@State var endPoint: CGFloat = 0
@State var yPoint: CGFloat = 0

var sliderWidth: CGFloat = 30
var containerWidth: CGFloat = 400
var containerHeight: CGFloat = 300

var body: some View {
    
    ZStack {
        
        ZStack() {
            Image("before_img")
                .resizable()
                .frame(width: containerWidth, height: containerHeight)
                .background(Color.red)
                .clipped()
            
            Image("after_img")
                .resizable()
                .frame(width: containerWidth, height: containerHeight)
                .clipped()
                .background(Color.green)
                .mask(mask)
        }
        .clipped()
        
        Slider
        
    }
    .clipped()
    .frame(width: containerWidth, height: containerHeight)
    .onAppear {
        yPoint = containerHeight/2
        location = CGPoint(x: containerWidth/2, y: yPoint)
        maskWidth = containerWidth/2
        endPoint = containerWidth
    }
}

var dragAction: some Gesture {
    DragGesture()
        .onChanged { value in
            updateDragView(point: value.location)
            updateMaskView(point: value.translation)
        }
        .onEnded { value in
            setInitialPosition()
        }
}

var mask: some View {
    HStack {
        Spacer()
        Rectangle()
            .mask(Color.black)
            .frame(width: maskWidth, height: containerHeight)
    }
}

var Slider: some View {
    VStack(spacing: 0) {
        Rectangle()
            .fill(Color.white)
            .frame(width: 4)
        Image(systemName: "circle.circle.fill")
            .foregroundColor(.white)
            .frame(width: sliderWidth, height: sliderWidth)
            .font(.system(size: sliderWidth))
        Rectangle()
            .fill(Color.white)
            .frame(width: 4)
    }
    .position(location)
    .gesture(dragAction)
    .shadow(radius: 4)
}

func updateDragView(point: CGPoint) {
    let locX = point.x
    if locX > startPoint && locX < endPoint {
        self.location = CGPoint(x: point.x, y: yPoint)
    }
}

func updateMaskView(point: CGSize) {
    let width = -(point.width)
    let newWidth = ((containerWidth/2)+width)
    if newWidth > 0 {
        maskWidth = ((containerWidth/2)+width)
    } else {
        setInitialPosition()
    }
}

func setInitialPosition() {
    withAnimation {
        location = CGPoint(x: containerWidth/2, y: yPoint)
        maskWidth = containerWidth/2
    }
}
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
john raja
  • 509
  • 4
  • 8
  • Create Solution, but I think it's better if the slider not return to middle after end dragging – Basel Aug 25 '22 at 07:10