SwiftUI:缩放 View 中的形状

标签 swift swiftui scaling

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

查看:

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

重用缩放 View :

(线宽缩放仍然存在一个小问题......)

enter image description here

代码:

import Foundation
import SwiftUI

struct MainView: View {

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

    var body: some View {
        VStack {
            HStack(spacing: 10) {
                SubView(color: $color)
            }
            .padding(10)
            HStack(spacing: 10) {
                SubView(color: $color)
                SubView(color: $color)
            }
            .padding(10)
            HStack(spacing: 10) {
                SubView(color: $color)
                SubView(color: $color)
                SubView(color: $color)
            }
            .padding(10)
        }
    }

}

struct ShapeView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()
    }
}

最佳答案

我现在使用applying(CGAffineTransform(a:, b: , c: , d:, tx: , ty: ))关于结果pathShape .

代码:

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

关于SwiftUI:缩放 View 中的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61883546/

相关文章:

ios - GMSMapView 防止 UIScrollView 滚动

ios - 仅将 SidebarListStyle() 应用于 Mac

kubernetes - 多个副本/Pod 如何扩展 Kubernetes?

java - JTA 上下文中 Hibernate(Flush?)的扩展问题

ios - 在没有 AutoLayout 效果的情况下缩放自定义 UIView 大小

ios - 声明 IBOutlet 时使用类型别名

ios - 当用户点击 "Play Again"时,如何在 Swift 中重置数组

swift - 如何禁用 SwiftUI View 上的用户交互?

swift - 如何使用 SwiftUI 将图像与列表行中的右角对齐?

ios - 如何将 MapView 中的注释链接到其调用引脚