In Swift calculate color without transparency obtained by overlaying a color with an transparant color
The alpha of the overlay color (a2
) tells you the percentage that color contributes to the total, and (1 - a2)
tells you the percentage the original color contributes. From that, it is a straightforward calculation:
func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
// Helper function to clamp values to range (0.0 ... 1.0)
func clampValue(_ v: CGFloat) -> CGFloat {
guard v > 0 else { return 0 }
guard v < 1 else { return 1 }
return v
}
var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
// Make sure the input colors are well behaved
// Components should be in the range (0.0 ... 1.0)
r1 = clampValue(r1)
g1 = clampValue(g1)
b1 = clampValue(b1)
r2 = clampValue(r2)
g2 = clampValue(g2)
b2 = clampValue(b2)
a2 = clampValue(a2)
let color = UIColor( red: r1 * (1 - a2) + r2 * a2,
green: g1 * (1 - a2) + g2 * a2,
blue: b1 * (1 - a2) + b2 * a2,
alpha: 1)
return color
}
Intuitively this checks out. If the overlay color is fully opaque (a2 == 1
) then the result will be the overlay color. If the overlay color is fully transparent (a2 == 0
), the result will be the original color. If the overlay color's alpha is 0.5
, you will get a blend that is exactly halfway between the two colors.
Testing it in a Playground:
// Make these colors anything you want
let c1 = UIColor(red: 27/255, green: 155/255, blue: 199/255, alpha: 1.0)
let c2 = UIColor(red: 188/255, green: 13/255, blue: 51/255, alpha: 0.37)
let c3 = calculateColor(orgColor: c1, overlayColor: c2)
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let view2 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view1.backgroundColor = c1
view2.backgroundColor = c2
// Overlay view2 onto view1
view1.addSubview(view2)
// view3 has the calculated color
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3
// display the views side by side in view4
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)
// display this view and see that the two halves match
view4
Playground output:
How to calculate result of overlaying two color integers with alpha channels on Android
I think this will blend colours respecting their alphas.
@ColorInt infix fun @receiver:ColorInt Int.overlay(@ColorInt bottomColor: Int): Int {
val topAlpha = Color.alpha(this)
val bottomAlpha = Color.alpha(bottomColor)
val alphaSum = bottomAlpha + topAlpha
return Color.argb(
Math.min(255, alphaSum),
(Color.red(bottomColor) * bottomAlpha + Color.red(this) * topAlpha) / alphaSum,
(Color.green(bottomColor) * bottomAlpha + Color.green(this) * topAlpha) / alphaSum,
(Color.blue(bottomColor) * bottomAlpha + Color.blue(this) * topAlpha) / alphaSum
)
}
NSAttributedString: How to mimic opacity or alpha equivalent using color
You can change any color alpha using
UIColor.red.withAlphaComponent(0.5)
Of course, you have to know the original color.
There is no universal alpha modifier.
Text opacity gradient
Just use .mask
instead.
struct ContentView: View {
var body: some View {
ZStack {
Color.red
Text("Hello world!")
/// for iOS 14 and below, replace { } with ( )
.mask {
/// no need for .opacity, just use .clear
LinearGradient(colors: [.white, .clear], startPoint: .leading, endPoint: .trailing)
}
}
}
}
Result:
How can I have an opaque UIView as a subview of a semi-transparent UIView?
No, not really. What you want is to take your overlay view, and make it just have a clear background color. As a subview of that new overlay place your view that will grey things out. And as a sibling view to that put your view you want to be opaque.
[OpaqueView] [DimmingView]
| |
[OverlayView]
Transparent UILabel textColor on superview.superview (sort of)
Since iOS 8 Apple offer a new class, UIVibrancyEffect, which can be added to a UIVisualEffectView. This combined with a UIBlurEffect can achieve the exact same result as my screenshot above.
Source: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVibrancyEffect/index.html
How to set the opacity of an overlay in SwiftUI
You're adding opacity to your whole view, add it to your overlay instead:
.overlay(Color.gray.opacity(0.1))
Overlay non transparent Pixels in iOS Cocoa
I think you are probably looking for the blend mode kCGBlendModeSourceAtop. First, draw the UIImage into your view. Then obtain the current graphics context with
CGContext currentCtx = UIGraphicsGetCurrentContext();
Then save the context state, and set the blend mode:
CGContextSaveGState(currentCtx);
CGContextSetBlendMode(currentCtx, kCGBlendModeSourceAtop);
Then you can draw whatever you want to be overlaid over the opaque pixels of the UIImage. Afterward, just reset the context state:
CGContextRestoreGState(currentCtx);
Hope this helps!
Related Topics
Is There a Github Markdown Language Identifier for Swift Code
Is There an Kotlin Equivalent 'With' Function in Swift
How to Change the Colour of Separator in List of Swiftui
Implemented Helper App But Does Not Launch on Login
Firebasecore Lexical or Preprocessor Issue
Swift Tdd & Async Urlsession - How to Test
How Convert a *Positive* Number into an Array of Digits in Swift
Bringing iOS Frameworks Through Carthage in Xcode 12.0
Delegate Property with Different Type in Swift
Swift Cannot Infer Type from Context
Saving a Codable Struct to Userdefaults with Swift
Dictionary of String:Any Does Not Conform to Protocol 'Decodable'