Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom cross-hatched background shape or view in SwiftUI

I am trying to create a shaded cross-hatched. But so far I can do it by adding a Image.

How can I create a custom view in which lines will be drawn and not filled with a Image?

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()
    }
}

This is how it looks now. Want lines to draw on top of another view or shape, without adding opacity and image pattern filling.

Cross-hatched shape

like image 302
flyer2001 Avatar asked Oct 20 '25 05:10

flyer2001


2 Answers

Thank to Cenk Bilgen for stripe pattern. Tweaked a bit so that you can rotate the hatch for any shape.

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))
    }
}

And usage

struct ContentView: View {

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

Output image link

like image 83
flyer2001 Avatar answered Oct 22 '25 03:10

flyer2001


I`m not sure what do you want but another possible solution is using different backgrounds in a ZStack linear gradient and shadows to make convex or concave effect., for this it helps that your background with a little color, not white white. some samples:

enter image description here

The code:

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)
    }
}
like image 27
dig Avatar answered Oct 22 '25 05:10

dig



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!