Sak*_*rda 8 ios swiftui sf-symbols
我正在尝试从 swiftUI 中的圆形中剪出一个 sf 符号。
我目前有以下代码:
Circle()
.fill(Color.white)
.frame(width: 50, height: 50)
.mask(
Image(systemName: "play.fill")
.font(.system(size: 24))
.foregroundColor(Color.black)
.frame(width: 50, height: 50)
)
Run Code Online (Sandbox Code Playgroud)
产生:
但是,我想要的是反转蒙版的效果:符号从圆圈中切出,如下图所示:
请注意,实际背景不是图像中的红色,而是用户上传的图像,因此无法将符号 foregroundColor 设置为红色。
有什么方法可以反转符号/图像的蒙版,使圆圈中有一个具有图像形状的孔?
对于切口,只需使用.blendMode(.destinationOut)和.compositingGroup()。无需重复形状、遮罩和定义白色/黑色。
var buttonCutOut: some View {
ZStack {
shape
mask.blendMode(.destinationOut)
}.compositingGroup()
}
Run Code Online (Sandbox Code Playgroud)
这是一个用于遮罩形状或亮度遮罩形状的可重用组件示例。
struct Demo: View {
var body: some View {
ZStack {
userImage.blur(radius: 5)
playButtons
}
}
var playButtons: some View {
VStack {
Mask(thisShape: Circle(),
with: maskImage,
offset: maskImageOffset,
maskToShapeRatio: maskImageToShapeRatio)
.frame(width: square, height: square)
.foregroundColor(colorDestinationOut)
LuminanceMask(thisShape: Circle(),
with: maskImage,
offset: maskImageOffset,
maskToShapeRatio: maskImageToShapeRatio)
.frame(width: square, height: square)
.foregroundColor(colorLuminanceAlpha)
}
.font(font)
}
}
struct Mask<S: Shape>: View {
init(thisShape: S,
with mask: Image,
offset: CGSize,
maskToShapeRatio: CGFloat) {
self.shape = thisShape
self.mask = mask
self.offset = offset
self.scale = maskToShapeRatio
}
let shape: S
let mask: Image
let offset: CGSize
let scale: CGFloat
var body: some View {
ZStack(alignment: .center) {
shape.fill()
mask
.resizable()
.offset(offset)
.aspectRatio(contentMode: .fit)
.blendMode(.destinationOut)
.scaleEffect(scale)
}.compositingGroup()
}
}
struct LuminanceMask<S: Shape>: View {
init(thisShape: S,
with mask: Image,
offset: CGSize,
maskToShapeRatio: CGFloat) {
self.shape = thisShape
self.mask = mask
self.offset = offset
self.scale = maskToShapeRatio
}
let shape: S
let mask: Image
let offset: CGSize
let scale: CGFloat
let keep = Color.white
let remove = Color.black
var body: some View {
shape.mask(maskView)
}
var maskView: some View {
ZStack(alignment: .center) {
shape
.foregroundColor(keep)
mask
.resizable()
.offset(offset)
.aspectRatio(contentMode: .fit)
.scaleEffect(scale)
.foregroundColor(remove)
}.compositingGroup()
.luminanceToAlpha()
}
}
Run Code Online (Sandbox Code Playgroud)
首先,让我们创建一个视图修饰符.inverseMask():
extension View {
// view.inverseMask(_:)
public func inverseMask<M: View>(_ mask: M) -> some View {
// exchange foreground and background
let inversed = mask
.foregroundColor(.black) // hide foreground
.background(Color.white) // let the background stand out
.compositingGroup() // ?? composite all layers
.luminanceToAlpha() // ?? turn luminance into alpha (opacity)
return self.mask(inversed)
}
}
Run Code Online (Sandbox Code Playgroud)
其次,让我们做一个演示视图:
请注意,我在以下代码中使用了自定义扩展名LinearGradient,它列在底部。
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
var body: some View {
// lightbulb image
let lightbulb = Image(systemName: "lightbulb")
.resizable().scaledToFit().padding(24)
// rounded rect (shape)
let roundedRect = RoundedRectangle(cornerRadius: 20)
// rounded rect (stroked border)
let border = roundedRect
.stroke(
Gradient.diagonal(.white, .black), // my custom extension
lineWidth: 2
)
// container
return ZStack {
// background color
Color.white.grayscale(0.3)
// rounded card
Gradient.horizontal(.gray, .black) // my custom extension
// ?? inverse mask
.inverseMask(lightbulb)
.shadow(color: Color.black.opacity(0.6), radius: 4, x: 4, y: 4)
.frame(width: 150, height: 200)
.clipShape(roundedRect)
.overlay(border)
.shadow(color: Color.white.opacity(0.9), radius: 18, x: -18, y: -18)
.shadow(color: Color.black.opacity(0.3), radius: 14, x: 14, y: 14)
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
Run Code Online (Sandbox Code Playgroud)
结果是:
----[编辑]----
Gradient如果您好奇,这是我的自定义扩展:
import SwiftUI
extension Gradient {
// general linear gradient ---------------------------
public static func linear(
from start: UnitPoint,
to end: UnitPoint,
colors : [Color] // use array
) -> LinearGradient
{
LinearGradient(
gradient : Gradient(colors: colors),
startPoint: start,
endPoint : end
)
}
public static func linear(
from start: UnitPoint,
to end: UnitPoint,
colors : Color... // use variadic parameter
) -> LinearGradient
{
linear(from: start, to: end, colors: colors)
}
// specialized linear gradients ------------------------
// top to bottom
public static func vertical(_ colors: Color...) -> LinearGradient {
linear(from: .top, to: .bottom, colors: colors)
}
// leading to trailing
public static func horizontal(_ colors: Color...) -> LinearGradient {
linear(from: .leading, to: .trailing, colors: colors)
}
// top leading to bottom trailing
public static func diagonal(_ colors: Color...) -> LinearGradient {
linear(from: .topLeading, to: .bottomTrailing, colors: colors)
}
// top leading to bottom trailing
public static func diagonal2(_ colors: Color...) -> LinearGradient {
linear(from: .bottomLeading, to: .topTrailing, colors: colors)
}
}
Run Code Online (Sandbox Code Playgroud)
哦,顺便说一句,也许这就是 OP 想要的:
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
var body: some View {
// background image
let background = Image("red stars.PNG")
// mask
let mask = Image(systemName: "play.circle.fill")
.font(.system(size: 100))
.scaledToFit() // center the mask
// container
return ZStack {
// background color
Color.white.grayscale(0.3)
// card
background
.inverseMask(mask) // ?? cut out the mask
// shadow for hole
.shadow(color: Color.black.opacity(0.7), radius: 3, x: 3, y: 3)
// highlight & shadow for border
.shadow(color: Color.white.opacity(0.9), radius: 18, x: -18, y: -18)
.shadow(color: Color.black.opacity(0.3), radius: 14, x: 14, y: 14)
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
Run Code Online (Sandbox Code Playgroud)
结果是:
弗拉德乐高的这个答案在这里应用时有效。
.black您可以使用要剪切的部分和.white要保留的部分创建蒙版。
(假设背景是红色,这就是它的样子)
Rectangle()
.foregroundColor(Color.white)
.mask(
ZStack {
Circle()
.fill(Color.white)
.frame(width: 50, height: 50)
Image(systemName: "play.fill")
.font(.system(size: 24))
.foregroundColor(Color.black)
}
.compositingGroup()
.luminanceToAlpha()
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2050 次 |
| 最近记录: |