Skip to content

Commit

Permalink
Add some depth / curvature to buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
mfikes committed Jan 27, 2024
1 parent daea42e commit 1395a69
Showing 1 changed file with 75 additions and 53 deletions.
128 changes: 75 additions & 53 deletions Impedance Converter/Impedance Converter/CursorsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct ToggleButton: View {
@State private var isPressed = false // State to track if the button is being pressed

var rectColor: Color = .gray // The constant color of the rectangle
var pressedRectColor: Color { rectColor.opacity(0.7) } // Darker color for pressed state
var pressedRectColor: Color { rectColor.adjusted(brightness: 0.8) } // Darker color for pressed state
var offCircleColor: Color = .black // Color of the circle when off
var onCircleColor: Color = .green // Color of the circle when on
var panelGapColor: Color = .black // Color of the gap between button and front panel
Expand All @@ -59,60 +59,82 @@ struct ToggleButton: View {
}

var body: some View {
// Use a custom gesture instead of Button
Canvas { context, size in
let panelGapWidth: CGFloat = min(size.width, size.height) * 0.11
let cornerRadius: CGFloat = 10

// Drawing the panel gap
let outerRect = CGRect(x: panelGapWidth / 2,
y: panelGapWidth / 2,
width: size.width - panelGapWidth,
height: size.height - panelGapWidth)
context.fill(Path(roundedRect: outerRect, cornerRadius: cornerRadius*1.1), with: .color(panelGapColor))

// Drawing the inner rectangle (button)
let innerRectSize: CGFloat = min(size.width, size.height) - 2 * panelGapWidth
let innerRect = CGRect(x: panelGapWidth,
y: panelGapWidth,
width: innerRectSize,
height: innerRectSize)
context.fill(Path(roundedRect: innerRect, cornerRadius: cornerRadius), with: .color(isPressed ? pressedRectColor : rectColor))

// Drawing the circle
let circleDiameter: CGFloat = innerRectSize / 4
let circleRect = CGRect(x: (size.width - circleDiameter) / 2,
y: (size.height - circleDiameter) / 2,
width: circleDiameter,
height: circleDiameter)
let circlePath = Path(ellipseIn: circleRect)

if isOn {
// Draw a blurred green circle
context.fill(circlePath, with: .color(onCircleColor))
context.addFilter(.blur(radius: 4))
context.fill(circlePath, with: .color(onCircleColor.adjusted(brightness: 1.1)))
} else {
// Draw a black circle
context.fill(circlePath, with: .color(offCircleColor))
ZStack {
// Use a custom gesture instead of Button
Canvas { context, size in
let panelGapWidth: CGFloat = min(size.width, size.height) * 0.11
let cornerRadius: CGFloat = 10

// Drawing the panel gap
let outerRect = CGRect(x: panelGapWidth / 2,
y: panelGapWidth / 2,
width: size.width - panelGapWidth,
height: size.height - panelGapWidth)
context.fill(Path(roundedRect: outerRect, cornerRadius: cornerRadius*1.1), with: .color(panelGapColor))

// Drawing the inner rectangle (button)
let innerRectSize: CGFloat = min(size.width, size.height) - 2 * panelGapWidth
let innerRect = CGRect(x: panelGapWidth,
y: panelGapWidth,
width: innerRectSize,
height: innerRectSize)
context.fill(Path(roundedRect: innerRect, cornerRadius: cornerRadius), with: .color(isPressed ? pressedRectColor : rectColor))

// Drawing the circle
let circleDiameter: CGFloat = innerRectSize / 4
let circleRect = CGRect(x: (size.width - circleDiameter) / 2,
y: (size.height - circleDiameter) / 2,
width: circleDiameter,
height: circleDiameter)
let circlePath = Path(ellipseIn: circleRect)

// Shiny edge
context.stroke(Path(roundedRect: innerRect, cornerRadius: cornerRadius), with: .color(isPressed ? pressedRectColor : rectColor.adjusted(brightness: 1.2)))

if isOn {
// Draw a blurred green circle and shiny edge blur
context.fill(circlePath, with: .color(onCircleColor))
context.addFilter(.blur(radius: 1))
context.stroke(Path(roundedRect: innerRect, cornerRadius: cornerRadius), with: .color(isPressed ? pressedRectColor : rectColor.adjusted(brightness: 1.2)))
context.addFilter(.blur(radius: 4))
context.fill(circlePath, with: .color(onCircleColor.adjusted(brightness: 1.1)))

} else {
// Draw a black circle
context.fill(circlePath, with: .color(offCircleColor))
// And shiny edge blur
context.addFilter(.blur(radius: 1))
context.stroke(Path(roundedRect: innerRect, cornerRadius: cornerRadius), with: .color(isPressed ? pressedRectColor : rectColor.adjusted(brightness: 1.2)))
}
}
}
.frame(width: 50, height: 50)
.aspectRatio(contentMode: .fit)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged({ _ in
if (!self.isPressed) {
self.isPressed = true
.frame(width: 50, height: 50)
.aspectRatio(contentMode: .fit)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged({ _ in
if (!self.isPressed) {
self.isPressed = true
playHapticFeedback()
}
})
.onEnded({ _ in
self.isPressed = false
playHapticFeedback()
}
})
.onEnded({ _ in
self.isPressed = false
playHapticFeedback()
self.isOn.toggle() // Toggle the state when the gesture ends
})
)
self.isOn.toggle() // Toggle the state when the gesture ends
})
)
GeometryReader { geometry in
RadialGradient(gradient: Gradient(colors: [Color.white.opacity(0.2), Color.white.opacity(0)]),
center: .center,
startRadius: 1,
endRadius: 20)
.scaleEffect(x: 1, y: 0.5, anchor: .bottom) // Scale in y-direction to create an ellipse
.frame(width: geometry.size.width, height: geometry.size.height)
.clipShape(Rectangle()) // Clip to the frame's bounds
}
.blendMode(.normal)
.allowsHitTesting(false)
}
}
}

Expand Down

0 comments on commit 1395a69

Please # to comment.