SwiftUI:缩放视图中的形状

问题描述 投票:0回答:2

我有一个[320]完美设计的SubView :)。我想让它缩小到最小100x100。现在,我在每个Shape中都使用比例因子。问题:在可重用的SwiftUI Shapes中,是否存在更通用的缩放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)
    }
}

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

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

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()
    }
}
swift swiftui scaling
2个回答
1
投票

我现在正在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


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))
    }
 }
© www.soinside.com 2019 - 2024. All rights reserved.