Image修饰符

  • 怎么运用Image制造图画
  • 怎么调整图画巨细
  • 怎么平铺图画
  • 怎么运用SF Symbols烘托图画
  • 怎么烘托突变
  • 何运用Image和其他View作为布景
  • 怎么制造solid shapes
  • 怎么一起填充和描边
  • 怎么运用trim()制造实体形状的一部分
  • 怎么运用VideoPlayer播映电影
  • 怎么运用SpriteView集成SpriteKit
  • 怎么从URL加载远程图画
  • 怎么运用SF Symbols取得自定义色彩和透明度
  • 怎么动态调整 SF Symbol的色彩
  • 怎么运用PhotosPicker挑选图片
  • 怎么运用PhotosPicker导入视频
  • 怎么制造SF Symbols动画
  • 怎么从色彩中读取详细RGB(红、绿、蓝)的值
  • 怎么组合图形并创立新图形
  • 怎么加载Assets中的自定义色彩

概述

文章首要分享SwiftUI Modifier的学习过程,将运用事例的办法进行阐明。内容深入浅出,对成果大部分进行了截图展示,也有偷闲的部分,不过测试代码是齐全的。假如想要运转成果,能够移步Github下载code -> github事例链接

1、怎么运用Image制造图画

运用Image视图在SwiftUI布局中烘托图画。它能够从你的Bundle、体系图标、UIImage等加载图画

//假如运用Xcode15构建,则能够从Bundle加载图画病运用内置静态特点将其显现在图画视图中
Image(.fullEnglishThumb)
    .resizable()
    .scaledToFit()
//假如是Xcode14以及一下,则需求饮用图画名称以字符串的办法
Image("full-english-thumb")

1.1、uiImage办法加载

你还能够从现有的UIImage加载,由于UIImage的初始化会默许加载一个named,而且回来一个可选图画,但是你需求承认这个named存在你的财物目录中

Image(uiImage: UIImage(named: "corn-on-the-cob-thumb")!)

1.2、Image(SystemName:)

假如你要运用Apple的SF Symbols图标集,你应该运用Image(SystemName:)

Image(systemName: "cloud.heavyrain.fill")
    .font(.largeTitle)

留意:运用font修饰符来调整SF符号,就跟文本相同,能够修正图片巨细

调试成果:

SwiftUI基础篇Image

2、怎么调整图画巨细

SwiftUI的Image视图能够以不同的办法缩放,就像UIImageView相同,默许情况下,图画视图会自动根据器内容调整巨细,这可能会是他们超出屏幕范围,假如增加了resizable()修饰符,则图画将自动调整巨细,以便填充到可用空间,无论是在你指定的结构中仍是屏幕上的任何空间中

2.1、resizable

Image(.allOutDonutsThumb)
     .resizable()
     .frame(width: 200)

2.2、aspectRatio

然而,这会导致图画的原始纵横比歪曲,由于它将在一切维度上拉伸以填充空间,假如你想坚持纵横比,能够运用aspectRatio的.fill或.fit修饰符

Image(.allOutDonutsThumb)
     .resizable()
     .aspectRatio(contentMode: .fit)
     .frame(width: 200)

调试成果:

SwiftUI基础篇Image

3、怎么平铺图画

假如SwiftUI被要求运用图画视图占用的空间超过图画设计的空间,它的默许行为是拉伸图画,使其合适你所要求的空间。然而,它不需求这样,它能够平铺图画(水平或垂直重复),以便填满空间。关键将resizable()修饰符与其resizingMode参数一起运用,能够是.stretch(默许)、tile(平铺)

Image(.allOutDonuts)
    .resizable(resizingMode: .tile)

3.1、capInsets

假如你只想平铺图画的一部分(或将一个或多个边际固定到图画视图的边际),那么能够为第一个参数供给边际刺进

Image(.cheeseToastie)
    .resizable(capInsets: EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20),
    resizingMode: .tile)

调试成果:

SwiftUI基础篇Image

4、怎么运用SF Symbols烘托图画

SwiftUI的Image视图答应咱们加载SF Symbols中2400图标中的恣意一个,其间的很多图标也能够运用多色

4.1、规范加载

要从Apple的SF Symbols加载图标,请运用Image(systemName:),传入要加载的图标字符串

Image(systemName: "moon.stars.fill")

4.2、.font(.largeTitle)

Image经过systemName办法初始化回来的成果是能够缩放和上色的

Image(systemName: "wind.snow")
    .font(.largeTitle)

4.3、foregroundStyle(.red)

foregroundStyle,对图画上色

Image(systemName: "cloud.heavyrain.fill")
    .font(.largeTitle)
    .foregroundStyle(.red)

4.4、.renderingMode(.original)

假如你运用的图画包含色彩,则能够运用多色形式.renderingMode(.original)

Image(systemName: "cloud.sun.rain.fill")
    .renderingMode(.original)
    .font(.largeTitle)
    .padding()
    .background(.black)
    .clipShape(Circle())

4.5、多色SF Symbols

你能够挑选将foregroundStyle()修饰符用于多色SF Symbols,这样的话,符号的部分从头上色

Image(systemName: "person.crop.circle.fill.badge.plus")
    .renderingMode(.original)
    .foregroundColor(.blue)
    .font(.largeTitle)

调试成果:

SwiftUI基础篇Image

5、怎么烘托突变

SwiftUI 为咱们供给了多种突变选项,一切这些选项都能够以多种办法运用。 假如你的环境是 iOS 16 或更高版别,则能够经过附加到您正在运用的任何色彩来取得精美简略的线性突变.gradient

Rectangle().fill(.blue.gradient)

5.1、LinearGradient

关于更高档的突变,或支撑iOS16之前的版别,你能够运用SwiftUI的内置突变类型来取得精准操控。例如:用red到blue的线性突变来烘托文本视图

Text("蜀道之难,难于上青天!")
    .padding()
    .foregroundStyle(.white)
    .font(.largeTitle)
    .background(
        LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing)
    )

色彩被指定为一个数组,你能够用更多数量的色彩构建更复杂的突变

Text("蜀道之难,难于上青天!")
    .padding()
    .foregroundStyle(.white)
    .font(.largeTitle)
    .background(
        LinearGradient(gradient: Gradient(colors: [Color.red, .green, Color.blue]), startPoint: .leading, endPoint: .trailing)
    )

5.2、RadialGradient

代替突变样式,请尝试RadialGradient、AngularGradient,这会经过各种色彩创立径向突变,从圆的中心一直到边际

Circle()
    .fill(
        RadialGradient(gradient: Gradient(colors: [.red, .yellow, .green, .blue, .purple]), center: .center, startRadius: 50, endRadius: 100)
    ).frame(width: 200 ,height: 200)

5.3、AngularGradient

创立一个角度突变(圆锥突变),循环显现各种色彩,回来到最初

Circle()
  .fill(
    AngularGradient(gradient: Gradient(colors: [.red, .yellow, .green, .blue, .purple, .red]), center: .center)
  )
  .frame(width: 200, height: 200)

5.4、strokeBorder -> ShapeStyle协议

由于RadialGradient、AngularGradient、突变类型都契合ShapeStyle协议,因此你能够将它们用于布景、填充和描边

Circle()
  .strokeBorder(
    AngularGradient.init(gradient: Gradient(colors: [.red, .yellow, .green, .blue, .purple, .red]), center: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, startAngle: .zero, endAngle: .degrees(360)),
    lineWidth: 30
  )
  .frame(width: 200, height: 200)

调试成果:

SwiftUI基础篇Image
SwiftUI基础篇Image

6、何运用Image和其他View作为布景

SwiftUI 没有用于显现布景色彩或图画的专用修饰符,而是让咱们运用background()修饰符指定任何类型的布景视图

6.1、Image作为Text的布景

Text(" Hacking With Swift")
    .foregroundStyle(.white)
    .font(.system(size: 48))
    .padding(50)
    .background(
        Image(.cornOnTheCob)
            .resizable()
    )

6.2、运用圆形作为布景

Text(" Hacking With Swift")
    .foregroundStyle(.black)
    .font(.system(size: 48))
    .padding(50)
    .background(
        Circle()
            .fill(.red)
            .frame(width: 50, height: 50)
    )

6.3、clipped()

默许情况下,布景视图会占据你一切的空间,能够用clipped()进行裁剪

Text("Hacking With Swift")
    .font(.largeTitle)
    .padding()
    .background(
        Circle()
            .fill(.red)
            .frame(width: 100, height: 100)
    )
    .clipped()

调试成果:

SwiftUI基础篇Image

7、怎么制造solid shapes

SwiftUI由很多种内置形状,例如矩形、圆形和圆角矩形

//200 * 200的赤色矩形
Rectangle()
    .fill(.red)
    .frame(width: 200, height: 200)
//100 * 100的蓝色圆形
Circle()
    .fill(.blue)
    .frame(width: 100, height: 100)
//圆角矩形
RoundedRectangle(cornerRadius: 25.0)
    .fill(.green)
    .frame(width: 150, height: 100)
// Capsule()是SwiftUI供给的一种特殊的圆角矩形,其间最短的边永远是完全圆角的,相似Slider布景视图
Capsule()
    .fill(.green)
    .frame(width: 150, height: 100)

调试成果:

SwiftUI基础篇Image

8、怎么一起填充和描边

在iOS17中,只需求堆叠修饰符就能够一起填充和描边

8.1、根底表明

Circle()
    .stroke(.red, lineWidth: 5)
    .fill(.green)
    .frame(width: 150, height: 150)

8.2 能够屡次调用,大圈套小圈

Circle()
    .stroke(.blue, lineWidth: 45)
    .stroke(.green, lineWidth: 35)
    .stroke(.yellow, lineWidth: 25)
    .stroke(.orange, lineWidth: 15)
    .stroke(.red, lineWidth: 5)
    .frame(width: 150, height: 150)

8.3、运用strokeBorder

在iOS16以及更低版别中,SwiftUI供给了fill()、stroke()、strokeBorder()修饰符来调整咱们制造形状的办法,但它不供给一起填充和描边的内置办法。但是咱们能够经过两种不同的办法取得相同的作用 运用strokeBorder()在形状周围增加边框,然后运用background()将其填充形状包含在内

Circle()
    .strokeBorder(.red, lineWidth: 20)
    .background(
        Circle()
            .fill(.orange)
    )
    .frame(width: 150, height: 150)

8.4、运用ZStack

ZStack {
    Circle()
        .fill(.orange)
    Circle()
        .strokeBorder(.red, lineWidth: 20)
}
.frame(width: 150, height: 150)

调试成果:

SwiftUI基础篇Image

9、怎么运用trim()制造实体形状的一部分

SwiftUI答应咱们运用其修饰符仅制造形状的笔画或许填充一部分trim(),该修饰符采用两个参数,开始值和结束值,范围都是0-1

9.1、trim

制造一个半圆

Circle()
    .trim(from: 0, to: 0.5)
    .frame(width: 200, height: 200)

9.2、rotationEffect

SwiftUI制造其形状时0度直接位于右侧,因此假如你想更改此设置,运用修正器rotationEffect()

Rectangle()
    .trim(from: 0, to: completionAmount)
    .stroke(.red, lineWidth: 20)
    .frame(width: 200, height: 200)
    .rotationEffect(.degrees(-90))
    .onReceive(timer, perform: { _ in
        withAnimation {
            if completionAmount == 1 {
                completionAmount = 0
            } else {
                completionAmount += 0.2
            }
        }
    })

调试成果:

SwiftUI基础篇Image
SwiftUI基础篇Image
SwiftUI基础篇Image
SwiftUI基础篇Image
SwiftUI基础篇Image

10、怎么运用VideoPlayer播映电影

SwiftUI的VideoPlayer能够从任何URL播映视频。需求导入AVKit结构

10.1、本地视频

VideoPlayer(player: AVPlayer(url: Bundle.main.url(forResource: "Video", withExtension: ".mp4")!))
    .frame(height: 400)

10.2、URL链接视频

VideoPlayer(player: AVPlayer(url: URL(string: "https://bit.ly/swswift")!))
    .frame(height: 400)

10.3、 增加水印

VideoPlayer(player: AVPlayer(url: Bundle.main.url(forResource: "Video", withExtension: ".mp4")!)) {
    VStack {
        Text("Watermark")
            .foregroundStyle(.black)
            .background(
                .white.opacity(0.7)
            )
    }
}
.frame(width: 400, height: 300)

调试成果:

SwiftUI基础篇Image
SwiftUI基础篇Image

11、怎么运用SpriteView集成SpriteKit

SwiftUI中能够的SpriteView能够烘托任何子类,假如有需求,SKScene能够调整场景巨细,创立一个游戏场景,无论点击哪里,这都会创立下落的盒子,并增加物理作用,你创立的游戏场景是完全交互式的,因此它的工作办法就像SKViewUIKit 中的惯例场景相同。

class FFGameScene: SKScene {
    override func didMove(to view: SKView) {
        physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let box = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
        box.position = location
        box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 50, height: 50))
        addChild(box)
    }
}
struct FFSpriteView: View {
    var scene: SKScene {
        let scene = FFGameScene()
        scene.size = CGSize(width: 300, height: 400)
        scene.scaleMode = .fill
        return scene
    }
    var body: some View {
        SpriteView(scene: scene)
            .frame(width: 300, height: 400)
            .ignoresSafeArea()
    }
}

调试成果:

SwiftUI基础篇Image

12、怎么从 URL 加载远程图画

SwiftUI的AsynImage用于从网上下载和显现远程图画的功用。只需求传递一个URL

12.1、根底表明

URL是可选参数,假如URL无效,将显现默许的灰色占位符。假如由于某种原因无法加载图画(用户离线、图画不存在),那么体系将持续显现相同的占位符图画

AsyncImage(url: URL(string: "https://www.6hu.cc/files/2023/07/1689271195-501ea3b44910587.jpg"), scale: 4)

12.2、指定frame

由于SwiftUI不知道下载的图画有多大,因此默许情况下AsyncImage在加载时具有灵敏的宽度和高度。因此假如你不指定固定的宽度和高度,在图画加载之前会占用很多空间,然后在图画加载之后会调整到正确的巨细。

AsyncImage(url: URL(string: "https://www.6hu.cc/files/2023/07/1689271195-501ea3b44910587.jpg")) { image in
    image.resizable()
} placeholder: {
    Color.green
}
.frame(width: 128, height: 128)
.clipShape(RoundedRectangle(cornerRadius: 25))

12.3、AsyncImagePhase

显现image加载过程,会有菊花的中间视图过度

AsyncImage(url: URL(string: "https://www.6hu.cc/files/2023/07/1689271195-501ea3b44910587.jpg")) { phase in
    switch phase {
    case .failure: Image(systemName: "photo") .font(.largeTitle)
    case .success(let image): image .resizable()
    default: ProgressView()
    }
}
.frame(width: 256, height: 256)
.clipShape(RoundedRectangle(cornerRadius: 25)) }

13、怎么运用 SF Symbols 取得自定义色彩和透明度

假如你在SwiftUIImage中运用SF Symbols,你能够运用foregroundStyle()修饰符取得单一的色彩,或许运用.renderingMode(.original)运用多色。

13.1、.symbolRenderingMode(.hierarchical)

分层烘托,用透明的办法制造图画以供给额定的深度和清晰度

Image(systemName: "theatermasks")
    .symbolRenderingMode(.hierarchical)
    .font(.system(size: 144))

13.2、.symbolRenderingMode(.hierarchical) + .foregroundStyle(.blue)

分层烘托与前景色结合运用,能够一起指定两者

Image(systemName: "theatermasks")
    .symbolRenderingMode(.hierarchical)
    .foregroundStyle(.blue)
    .font(.system(size: 144))

13.3、.symbolRenderingMode(.palette)

.palette,完全操控图画中的色彩,悉数自己指定

Image(systemName: "shareplay")
    .symbolRenderingMode(.palette)
    .foregroundStyle(.blue, .black)
    .font(.system(size: 144))

13.4、.palette + .foregroundStyle(.blue, .green, .red)

这些色彩的应用办法取决于每个独自的符号 – 有时符号是用两层定义的,有时是三层

Image(systemName: "person.3.sequence.fill")
    .symbolRenderingMode(.palette)
    .foregroundStyle(.blue, .green, .red)
    .font(.system(size: 144))

13.5、linearGradient

增加突变

Image(systemName: "person.3.sequence.fill")
    .symbolRenderingMode(.palette)
    .foregroundStyle(
        .linearGradient(colors: [.red, .black], startPoint: .top, endPoint: .bottomTrailing),
        .linearGradient(colors: [.green, .black], startPoint: .top, endPoint: .bottomTrailing),
        .linearGradient(colors: [.blue, .black], startPoint: .top, endPoint: .bottomTrailing)
    )
    .font(.system(size: 144))

调试成果:

SwiftUI基础篇Image
SwiftUI基础篇Image

14、怎么动态调整 SF Symbol的色彩

某些SF Symbols支撑动态上色,操控范围在0-1之间

@State private var value = 0.0
var body: some View {
    List {
        Section {
            //部分填充的Wi-Fi
            Image(systemName: "wifi", variableValue: 0.5)
        }
        Section {
            //经过Slider滑动动态修正填充值
            Image(systemName: "aqi.low", variableValue: value)
            Image(systemName: "wifi", variableValue: value)
            Image(systemName: "chart.bar.fill", variableValue: value)
            Image(systemName: "waveform", variableValue: value)
            Slider(value: $value)
        }
        .font(.system(size: 72))
        .foregroundStyle(.blue)
        .padding()
    }
}

15、怎么运用PhotosPicker挑选图片

SwiftUIPhitisPicker能够运用体系规范图片导入界面,答应用户挑选一张或多张图片以及视频导入你的应用程序。假如运用它来导入图画,你需求导入PhotosUI,然后创立存储PhotosPickerItem来保存用户挑选的内容,并创立一个Image特点来存储加载的资源。 这组代码相对复杂一些,不好做拆分,假如想调试,全体copy一下,自己研究吧

struct FFImagePhotosPicker: View {
    @State private var avatarItem: PhotosPickerItem?
    @State private var avatarImage: Image?
    @State private var selectedItems = [PhotosPickerItem]()
    @State private var selectedImages = [Image]()
    var body: some View {
        /**
         假如您想更好地操控所选数据,请matching根据您要查找的内容调整参数:
         matching: .screenshots假如您只需求屏幕截图,请运用。
         matching: .any(of: [.panoramas, .screenshots])假如您想要其间任何一种类型,请运用。
         matching: .not(.videos)假如您想要非视频的任何媒体,请运用。
         matching: .any(of: [.images, .not(.screenshots)]))假如您想要除屏幕截图之外的一切类型的图画,请运用。
         */
        List {
            Section {
                PhotosPicker("Select acatar", selection: $avatarItem, matching: .images)
                if let avatarImage {
                    avatarImage
                        .resizable()
                        .scaledToFit()
                        .frame(width: 300, height: 300)
                }
            }
            .onChange(of: avatarItem) {
                Task {
                    if let data = try? await avatarItem?.loadTransferable(type: Data.self) {
                        if let uiImage = UIImage(data: data) {
                            avatarImage = Image(uiImage: uiImage)
                            return
                        }
                    }
                }
            }
            Section {
                PhotosPicker("Select Images", selection: $selectedItems, matching: .images)
                    .onChange(of: selectedItems) {
                        Task {
                            selectedImages.removeAll()
                            for item in selectedItems {
                                if let data = try? await item.loadTransferable(type: Data.self) {
                                    if let uiImage = UIImage(data: data) {
                                        let image = Image(uiImage: uiImage)
                                        selectedImages.append(image)
                                    }
                                }
                            }
                        }
                    }
                ForEach(0..<selectedImages.count, id: \.self) { i in
                    selectedImages[i]
                        .resizable()
                        .scaledToFit()
                        .frame(width: 300 ,height: 300)
                }
            }
        }
    }
}

调试成果:

SwiftUI基础篇Image

16、怎么运用PhotosPicker导入视频

  1. 导入AVKit以拜访VideoPlayer视图,导入PhotosUI拜访PhotosPicker视图
  2. 自定义Movie结构体是告知程序导入movie数据的办法,Transferable能够经过URL运用SentTransferredFile来发送数据,这意味着我能够讲Movie实例拖出应用程序,它还能够运用必报承受数据,它将movie的URL转换成movie.mp4的办法复制到我的文档目录,并删除任何现有的文件
  3. 导入movie可能需求一些时刻,因此我需求承认用户在后台应用程序运转时后了解咱们的导入状况,经过4种状况来处理的:
    • unknown当应用程序启动时
    • loading显现进度旋转器
    • loaded当movie导入完结
    • failed导入失利
  4. 在onChange修饰符种,要求体系为咱们供给一个Movie实例,以便咱们承受URL并将其转移到正确的方位供给给app,这还负责设置loadState特点,坚持UI同步

Transferable

struct Movie: Transferable {
    let url: URL
    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .movie) { movie in
            SentTransferredFile(movie.url)
        } importing: { received in
            let copy = URL.documentsDirectory.appending(path: "movie.mp4")
            if FileManager.default.fileExists(atPath: copy.path()) {
                try FileManager.default.removeItem(at: copy)
            }
            try FileManager.default.copyItem(at: received.file, to: copy)
            return self.init(url: copy)
        }
    }
}

PhotosPicker

struct FFImageVideo: View {
    enum LoadState {
        case unknown, loading, loaded(Movie), failed
    }
    @State private var selectedItem: PhotosPickerItem?
    @State private var loadState = LoadState.unknown
    var body: some View {
        List {
            PhotosPicker("Select movie", selection: $selectedItem, matching: .videos)
                .onChange(of: selectedItem) {
                    Task {
                        do {
                            loadState = .loading
                            if let movie = try await selectedItem?.loadTransferable(type: Movie.self) {
                                loadState = .loaded(movie)
                            } else {
                                loadState = .failed
                            }
                        } catch {
                            loadState = .failed
                        }
                    }
                }
            switch loadState {
            case .unknown:
                EmptyView()
            case .loading:
                ProgressView()
            case .loaded(let movie):
                VideoPlayer(player: AVPlayer(url: movie.url))
                    .scaledToFit()
                    .frame(width: 300, height: 300)
            case .failed:
                Text("Import failed")
            }
        }
    }
}

调试成果:

我运用的模拟器来测试的,没有Video,用真机跑一下就好了。本人偷闲了…

17、怎么制造SF Symbols动画

SwiftUI供给了symbolEffect()修饰符来为SF Symbol增加内置动画作用,

17.1、symbolEffect

点击button,小狗图标跳动一次

Button {
    petCount += 1
} label: {
    Label("Pet the Dog", systemImage: "dog")
}
.symbolEffect(.bounce, value: petCount)
.font(.largeTitle)

17.2、调整动画的方向

Button {
    isFavorite.toggle()
} label: {
    Label("Activate Inbox Zero", systemImage: "mail.stack")
}
.symbolEffect(.bounce.down, value: isFavorite)
.font(.largeTitle)

17.3、options: .speed(3).repeat(3)

增加额定的选项来取得重复计数和自定义速度

Button {
    isFavorite.toggle()
} label: {
    Label("Activate Inbox Zero", systemImage: "mail.stack")
}
.symbolEffect(.bounce.down, options: .speed(3).repeat(3),value: isFavorite)
.font(.largeTitle)

17.4、iterative、cumulative

/可变色彩动画特别强壮,由于SF Symbols能够让你操控每个图层的动画 .variableColor.iterative:一次为一个图层做色,.variableColor.cumulative将每个新图层增加到先前的上色图层中,而且能够运用reversing到其间任何一个来制造动画是向前播映仍是向后播映

Button("Start Animations") {
    withAnimation {
        animationsRunning.toggle()
    }
}
HStack {
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.iterative, value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.cumulative, value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.reversing.iterative, value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.reversing.cumulative, value: animationsRunning)
}
.font(.largeTitle)
HStack {
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.iterative,options: .repeating, value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.cumulative,options: .repeat(3), value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.reversing.iterative, options: .speed(3), value: animationsRunning)
    Image(systemName: "square.stack.3d.up")
        .symbolEffect(.variableColor.reversing.cumulative, options: .repeat(3).speed(3), value: animationsRunning)
}
.font(.largeTitle)

17.5、contentTransition

假如经过点击与用户交互,切换图标,运用修饰符contentTransition()

Button{
    withAnimation {
        isFavorite.toggle()
    }
} label: {
    Label("Toggle Favorite", systemImage: isFavorite ? "checkmark" : "heart")
}
.contentTransition(.symbolEffect(.replace))
.font(.largeTitle)

调试成果:

由于这部分代码都是关于动画的,我只上传了一张图,仅供参考,想看实践动画,移步Github

SwiftUI基础篇Image

18、怎么从色彩中读取详细RGB(红、绿、蓝)的值

SwiftUI的Color视图并不是保留一种特定的色彩,而是在屏幕上制造时才解析为特定值。这答应体系运用明暗形式之间的纤细变化来确保最佳,但这也意味着取得市级的红绿蓝分别是什么的唯一办法是询问解析的色彩。

  1. 获取当前环境的拜访权限,并将其传递到对你的色彩调用函数resolve(in:).Codable。
  2. 保存数据

18.1、根底表明

RGB分量的数据格式为Float,而不是double

@Environment(\.self) var environment
@State private var color = Color.red
@State private var resolvedColor: Color.Resolved?
func getColor() {
    resolvedColor = color.resolve(in: environment)
}
ColorPicker("Select your favorite color", selection: $color)
    .onChange(of: color, initial: true, getColor)
if let resolvedColor {
    Text("Red: \(resolvedColor.red)")
    Text("Green: \(resolvedColor.green)")
    Text("Blue: \(resolvedColor.blue)")
    Text("Opacity: \(resolvedColor.opacity)")
}

18.2、将色彩数据解析为json

@Environment(\.self) var environment
@State private var color = Color.red
@State private var resolvedColor: Color.Resolved?
@State private var colorJSON = ""
func getColor() {
    resolvedColor = color.resolve(in: environment)
    if let colorData = try? JSONEncoder().encode(resolvedColor) {
        colorJSON = String(decoding: colorData, as: UTF8.self)
    }
}
ColorPicker("Select your favorite color", selection: $color)
    .onChange(of: color, initial: true, getColor)
if let resolvedColor {
    Text("Red: \(resolvedColor.red)")
    Text("Green: \(resolvedColor.green)")
    Text("Blue: \(resolvedColor.blue)")
}
Text("Color JSON: \(colorJSON)")

18.3、转化为实例Color

let resolvedColor = Color.Resolved(red: 0, green: 0.6, blue: 0.9)
Rectangle()
    .fill(
        Color(resolvedColor).gradient
    )

调试成果:

SwiftUI基础篇Image

19、怎么组合图形并创立新图形

一切SwiftUI的图形都能够经过各种办法组合来创立新的图形,包括并集(合并两个图形的填充区域),交集(包含两个图形中共有区域的填充区域),线交集(回来一个图形的线填充另一个)

19.1、union

将一个圆形与刺进100个点的capsule组合起来,并填充为蓝色

Circle()
    .union(.capsule(style: .circular))
    .fill(.blue)

19.2、lineSubtraction

lineSubtraction()在圆形中切出矩形,用圆帽描边剩下部分

Circle()
    .lineSubtraction(.rect.inset(by: 30))
    .stroke(style: .init(lineWidth: 20, lineCap: .round))
    .padding()

19.3、symmetricDifference

将一个圆放在左边,然后减去另一个向右偏移的圆

Circle()
    .offset(x: 0)
    .symmetricDifference(.circle.offset(x: 100))
    .fill(.red)
    .frame(width: 200, height: 200)
    .padding()

调试成果:

SwiftUI基础篇Image

20、怎么加载Assets中的自定义色彩

在Assets中创立 色彩是可视化它们最好的办法,也是增加深色与淡色形式调整的简略办法(在Assets中增加color set能够一起分别设定深色与淡色形式)创立办法Assets catalog -> add -> Color Set

SwiftUI基础篇Image

List {
    Section {
        Color(.customAssets)
    }
    Section {
        Color(.ff)
    }
}

调试成果:

SwiftUI基础篇Image