SwiftUI:在视图中缩放形状
SwiftUI: Scaling a Shape in a View
我有一个 SubView
完美设计的 320x320 :)。我想让它缩小到最小 100x100。现在我在每个 Shape
中使用一个比例因子。问题:在可重用的 SwiftUI View
中是否有更通用的缩放方式 Shapes
(尺寸、线条宽度和长度以及矩形宽度和高度)?谢谢。
查看:
代码:
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)
}
}
通过缩放重复使用的视图:
(线宽缩放还有个小问题...)
代码:
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()
}
}
这是不准确的部分重叠的结果。我喜欢它在 SubView
的结构更改后的样子(或类似的东西,即上刻度应该比下刻度更宽)
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))
}
}
我现在正在 applying(CGAffineTransform(a:, b: , c: , d:, tx: , ty: ))
使用 Shape
中的结果 path
。
代码:
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)
}
}
看:
我有一个 SubView
完美设计的 320x320 :)。我想让它缩小到最小 100x100。现在我在每个 Shape
中使用一个比例因子。问题:在可重用的 SwiftUI View
中是否有更通用的缩放方式 Shapes
(尺寸、线条宽度和长度以及矩形宽度和高度)?谢谢。
查看:
代码:
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)
}
}
通过缩放重复使用的视图:
(线宽缩放还有个小问题...)
代码:
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()
}
}
这是不准确的部分重叠的结果。我喜欢它在 SubView
的结构更改后的样子(或类似的东西,即上刻度应该比下刻度更宽)
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))
}
}
我现在正在 applying(CGAffineTransform(a:, b: , c: , d:, tx: , ty: ))
使用 Shape
中的结果 path
。
代码:
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)
}
}