SwiftUI中的自定义交叉阴影背景形状或视图

SwiftUI中的自定义交叉阴影背景形状或视图,swiftui,draw,shapes,Swiftui,Draw,Shapes,我正在尝试创建一个阴影交叉阴影。但到目前为止,我可以通过添加图像来实现 如何创建一个自定义视图,在该视图中绘制线而不填充图像 import SwiftUI struct ContentView: View { var body: some View { ZStack { Image("lineFilledBG").resizable().clipShape(Circle()) Circle().str

我正在尝试创建一个阴影交叉阴影。但到目前为止,我可以通过添加图像来实现

如何创建一个自定义视图,在该视图中绘制线而不填充图像

import SwiftUI

struct ContentView: View {

    var body: some View {
        ZStack {
            Image("lineFilledBG").resizable().clipShape(Circle())
            Circle().stroke()
            Circle().foregroundColor(.yellow).opacity(0.3)
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
这就是现在的样子。希望在另一个视图或形状的顶部绘制线条,而不添加不透明度和图像填充图案


我不确定这是否是您想要的,但CoreImage可以生成剥离图案

import CoreImage.CIFilterBuiltins
import SwiftUI

extension CGImage {
  // width is for total, ratio is second stripe relative to full width
  static func stripes(colors: (UIColor, UIColor), width: CGFloat, ratio: CGFloat) -> CGImage {
    let filter = CIFilter.stripesGenerator()
    filter.color0 = CIColor(color: colors.0)
    filter.color1 = CIColor(color: colors.1)
    filter.width = Float(width-width*ratio) 
    filter.center = CGPoint(x: width, y: 0)
    let size = CGSize(width: width+width*ratio, height: 1)
    let bounds = CGRect(origin: .zero, size: size)
    // keep a reference to a CIContext if calling this often
    return CIContext().createCGImage(filter.outputImage!.clamped(to: bounds), from: bounds)!
  }
}
然后使用ImagePaint

 Circle().fill(
   ImagePaint(image: Image(decorative: CGImage.stripes(colors: (.blue, .yellow), width: 80, ratio: 0.25), scale: 1))
   )
   .rotationEffect(.degrees(-30))

CILineScreen
过滤器可能更符合您的要求。

我不确定您想要什么,但另一种可能的解决方案是在ZStack线性渐变和阴影中使用不同的背景,以产生凸凹效果。因此,它有助于您的背景有一点颜色,而不是白色。一些样本:

守则:

struct ContentView: View {

    var body: some View {
        ZStack {
            Color.yellow.opacity(0.1)
            VStack(spacing: 50) {
                myCircle()
                myCircle1()
            }
        }
    }
}

struct myCircle: View {
    
    var body: some View {
        Circle().foregroundColor(Color.clear)
            .frame(width: 100, height: 100)
            .background(
                ZStack {
                    LinearGradient(gradient: Gradient(colors: [Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1))]), startPoint: .topLeading, endPoint: .bottomTrailing)
                    Circle()
                        .stroke(Color.clear, lineWidth: 10)
                        .shadow(color: Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 3, x: -5, y: -5)
                    Circle()
                        .stroke(Color.clear, lineWidth: 10)
                        .shadow(color: Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1)), radius: 3, x: 3, y: 3)
                }
            )
            .clipShape(Circle())
            .shadow(color: Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), radius: 20, x: -20, y: -20)
            .shadow(color: Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), radius: 20, x: 20, y: 20)
    }
}

struct myCircle1: View {
   
    var body: some View {
       Circle().foregroundColor(Color.clear)
        .frame(width: 100, height: 100)
        .background(
            ZStack {
                LinearGradient(gradient: Gradient(colors: [Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1))]), startPoint: .topLeading, endPoint: .bottomTrailing)
                Circle()
                    .stroke(Color.clear, lineWidth: 10)
                    .shadow(color: Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 3, x: -5, y: -5)
                Circle()
                    .stroke(Color.clear, lineWidth: 10)
                    .shadow(color: Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1)), radius: 3, x: 3, y: 3)
            }
        )
        .clipShape(Circle())
        .shadow(color: Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), radius: 20, x: -20, y: -20)
        .shadow(color: Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), radius: 20, x: 20, y: 20)
    }
}
谢谢你的条纹图案。稍微调整了一下,以便可以旋转任何形状的图案填充

import SwiftUI
import CoreImage.CIFilterBuiltins

extension CGImage {

    static func generateStripePattern(
        colors: (UIColor, UIColor) = (.clear, .black),
        width: CGFloat = 6,
        ratio: CGFloat = 1) -> CGImage? {

    let context = CIContext()
    let stripes = CIFilter.stripesGenerator()
    stripes.color0 = CIColor(color: colors.0)
    stripes.color1 = CIColor(color: colors.1)
    stripes.width = Float(width)
    stripes.center = CGPoint(x: 1-width*ratio, y: 0)
    let size = CGSize(width: width, height: 1)

    guard
        let stripesImage = stripes.outputImage,
        let image = context.createCGImage(stripesImage, from: CGRect(origin: .zero, size: size))
    else { return nil }
    return image
  }
}

extension Shape {

    func stripes(angle: Double = 45) -> AnyView {
        guard
            let stripePattern = CGImage.generateStripePattern()
        else { return AnyView(self)}

        return AnyView(Rectangle().fill(ImagePaint(
            image: Image(decorative: stripePattern, scale: 1.0)))
        .scaleEffect(2)
        .rotationEffect(.degrees(angle))
        .clipShape(self))
    }
}
用法

struct ContentView: View {

    var body: some View {
        VStack {
            Rectangle()
                .stripes(angle: 30)
            Circle().stripes()
            Capsule().stripes(angle: 90)
        }
    }
}

它适用于圆形,但当您需要将图案填充旋转为其他形状时,结果是“是”,它只生成垂直条纹。因此,如果要将最终结果旋转到任意角度,它实际上只适用于圆。要使其适用于任何形状,您可以在图像创建阶段应用旋转变换。谢谢。根据您的回答添加了旋转,我希望我正确地理解了您)请查看我的回答有一点让我头疼(看起来它在@flyer2001的解决方案中是固定的),那就是旋转传递到ImagePaint中的图像并不像您想象的那样工作。它看起来像是在引擎盖下弹出了一个
SwiftUI.ModifiedContent
视图,而不是一个新的SwiftUI.Image。如果您需要最终结果是一个图像而不是一个视图,请调整函数以对CIImage应用旋转或任何变换,然后将CGImage边界设置为您想要的最终图像的大小。然后从该CGImage初始化SwiftUI映像。