SwiftUI:在视图中缩放形状

时间:2020-05-19 04:57:49

标签: swift swiftui scaling

我有一个{320.x320:320)的完美设计。我想让它缩小到最小100x100。现在,我在每个SubView中使用比例因子。问题:在可重用的SwiftUI Shape中,是否存在更通用的缩放Shapes的方式(尺寸,线条的宽度和长度以及矩形的宽度和高度)?谢谢。

查看:

enter image description here

代码:

View

具有缩放比例的重用视图:

(线宽缩放还有一个小问题……)

enter image description here

代码:

import SwiftUI

private struct SecondsFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let square = CGRect(x: rect.minX, y: rect.minY, width: min(rect.maxX-rect.minX,rect.maxY-rect.minY), height: min(rect.maxX-rect.minX,rect.maxY-rect.minY))
        let scaleFactor = CGFloat(square.width / 320.0)
        var seconds : Path = Path()
        seconds.addLines([CGPoint(x: (320.0/2.0-14.0)*scaleFactor, y: 0),CGPoint(x: (320.0/2-4.0)*scaleFactor, y: 0)])
        for i in 0...59 {
            path.addPath(seconds, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/60.0))
        }
        return path.offsetBy(dx: (320.0/2.0)*scaleFactor, dy: (320.0/2.0)*scaleFactor)
    }
}

private struct HoursFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let square = CGRect(x: rect.minX, y: rect.minY, width: min(rect.maxX-rect.minX,rect.maxY-rect.minY), height: min(rect.maxX-rect.minX,rect.maxY-rect.minY))
        let scaleFactor = CGFloat(square.width / 320.0)
        var seconds : Path = Path()
        seconds.addLines([CGPoint(x: (320.0/2.0-16)*scaleFactor, y: 0),CGPoint(x: (320.0/2.0-2.0)*scaleFactor, y: 0)])
        for i in 0...11 {
            path.addPath(seconds, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/12.0))
        }
        return path.offsetBy(dx: (320.0/2.0)*scaleFactor, dy: (320.0/2.0)*scaleFactor)
    }
}

struct ThreeHoursFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let square = CGRect(x: rect.minX, y: rect.minY, width: min(rect.maxX-rect.minX,rect.maxY-rect.minY), height: min(rect.maxX-rect.minX,rect.maxY-rect.minY))
        let scaleFactor = CGFloat(square.width / 320.0)
        let threehours : Path = Path(CGRect(x: (320.0/2.0-20.0)*scaleFactor, y: -2.0*scaleFactor, width: 20.0*scaleFactor, height: 4.0*scaleFactor))
        for i in 0...3 {
            path.addPath(threehours, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/4.0))
            }
        return path.offsetBy(dx: (320.0/2.0)*scaleFactor, dy: (320.0/2.0)*scaleFactor)
    }
}

struct SubView: View {
    @Binding var color : ColorValue

    var body: some View {
        ZStack {
            SecondsFace()
            .stroke(Color.green, style: StrokeStyle(lineWidth: 1, lineCap: .square, lineJoin: .bevel))
            HoursFace()
            .stroke(Color.red, style: StrokeStyle(lineWidth: 3, lineCap: .square, lineJoin: .bevel))
            ThreeHoursFace()
            .fill(Color.blue)
        }
        .aspectRatio(1, contentMode: .fit)
        .clipped(antialiased: true)
        .background(Color(red: 0.9, green: 0.9, blue: 0.9, opacity: 1.0))
    }
 }

struct SubViewPreview: PreviewProvider {

    @State static var currentColor : ColorValue = ColorValue(color: UIColor.red)

    static var previews: some View {
        SubView(color: $currentColor)
    }
}

2 个答案:

答案 0 :(得分:0)

是不准确的零件重叠的结果。我喜欢SubView的更改构造,如下所示(或类似的内容,即较高的刻度线应宽于较低的刻度线)

demo

struct SubViewA: View {
    @Binding var color : ColorValue

    var body: some View {
        ZStack {
            SecondsFace()
            .stroke(Color.green, style: StrokeStyle(lineWidth: 1, lineCap: .square, lineJoin: .bevel))
            HoursFace()
            .stroke(Color.red, style: StrokeStyle(lineWidth: 2, lineCap: .square, lineJoin: .bevel))
            ThreeHoursFace()
            .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .square, lineJoin: .bevel))
        }
        .aspectRatio(1, contentMode: .fit)
        .clipped(antialiased: true)
        .background(Color(red: 0.9, green: 0.9, blue: 0.9, opacity: 1.0))
    }
 }

答案 1 :(得分:0)

我现在在applying(CGAffineTransform(a:, b: , c: , d:, tx: , ty: ))中的结果path上使用Shape

代码:

import SwiftUI

private struct SecondsFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let seconds : Path = Path(CGRect(x: (320.0/2.0-14.0), y: -1.0, width: 10.0, height: 2.0))
        for i in 0...59 {
            path.addPath(seconds, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/60.0))
        }
        let scaleFactor = CGFloat(min(rect.maxX-rect.minX,rect.maxY-rect.minY) / 320.0)
        return path.applying(CGAffineTransform(a: scaleFactor, b: 0.0, c: 0.0, d: scaleFactor, tx: (320.0/2.0)*scaleFactor, ty: (320.0/2.0)*scaleFactor))
    }
}

private struct HoursFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let seconds : Path = Path(CGRect(x: (320.0/2.0-16.0), y: -2.0, width: 14.0, height: 4.0))
        for i in 0...11 {
            path.addPath(seconds, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/12.0))
        }
        let scaleFactor = CGFloat(min(rect.maxX-rect.minX,rect.maxY-rect.minY) / 320.0)
        return path.applying(CGAffineTransform(a: scaleFactor, b: 0.0, c: 0.0, d: scaleFactor, tx: (320.0/2.0)*scaleFactor, ty: (320.0/2.0)*scaleFactor))
    }
}

struct ThreeHoursFace: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let threehours : Path = Path(CGRect(x: (320.0/2.0-24.0), y: -4.0, width: 24.0, height: 8.0))
        for i in 0...3 {
            path.addPath(threehours, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(i)/4.0))
        }
        let scaleFactor = CGFloat(min(rect.maxX-rect.minX,rect.maxY-rect.minY) / 320.0)
        return path.applying(CGAffineTransform(a: scaleFactor, b: 0.0, c: 0.0, d: scaleFactor, tx: (320.0/2.0)*scaleFactor, ty: (320.0/2.0)*scaleFactor))
    }
}

struct SubView: View {
    @Binding var color : ColorValue

    var body: some View {
        ZStack {
            SecondsFace()
            .fill(Color.green)
            HoursFace()
            .fill(Color.red)
            ThreeHoursFace()
            .fill(Color.blue)
        }
        .aspectRatio(1, contentMode: .fit)
        .clipped(antialiased: true)
        .background(Color(red: 0.9, green: 0.9, blue: 0.9, opacity: 1.0))
    }
 }

struct SubViewPreview: PreviewProvider {

    @State static var currentColor : ColorValue = ColorValue(color: UIColor.red)

    static var previews: some View {
        SubView(color: $currentColor)
    }
}

看:

enter image description here