Vortex logo

Twitter: @twostraws

Vortex 是一个强大的、高性能的 SwiftUI 粒子系统库,让你只需几行代码就能创建漂亮的特效,比如火焰、雨、烟和雪。

Vortex 内置了一系列特效,比如烟花、魔法、彩屑等等,但你也可以创建完全自定义的特效,以满足你的需求。

此框架兼容 iOS、macOS、tvOS、watchOS 和 visionOS。

安装

Vortex 使用 Swift Package Manager,所以你应该使用 Xcode 添加一个包依赖项,地址为 https://github.com/twostraws/Vortex

完成之后,在你的 Swift 代码中需要的地方导入 Vortex

import Vortex

在这个仓库的 Assets 目录中,你会找到三个示例粒子图像供你使用,但你也可以使用各种 SwiftUI 视图和形状,而不仅仅是图像。

查看实际效果

这个仓库包含一个跨平台示例项目,演示了所有预设的使用。该示例项目使用 SwiftUI 构建,需要 iOS 17、macOS 14 或 visionOS 1。

The Vortex Sandbox app demonstrating several built-in particle presets.

基本用法

渲染 Vortex 粒子系统需要两个步骤

  1. 创建 VortexSystem 的一个实例,并配置你希望粒子如何表现。 必须提供要渲染的粒子的标签名称列表。
  2. 将一个 VortexView 添加到你的 SwiftUI 视图层级中,传入要渲染的粒子系统,以及用于粒子的所有视图,并使用步骤 1 中的相同名称进行标记。

有很多内置的粒子系统设计,比如雨

VortexView(.rain) {
    Circle()
        .fill(.white)
        .frame(width: 32)
        .tag("circle")
}

烟花

VortexView(.fireworks) {
    Circle()
        .fill(.white)
        .blendMode(.plusLighter)
        .frame(width: 32)
        .tag("circle")
}

和火焰

VortexView(.fire) {
    Circle()
        .fill(.white)
        .blendMode(.plusLighter)
        .blur(radius: 3)
        .frame(width: 32)
        .tag("circle")
}

注意

每个预设都旨在查找一个或多个标签;请查看下面的文档以获取正确的标签。

你也可以创建完全自定义的效果,比如这样

struct ContentView: View {
    var body: some View {
        VortexView(createSnow()) {
            Circle()
                .fill(.white)
                .blur(radius: 5)
                .frame(width: 32)
                .tag("circle")
        }
    }

    func createSnow() -> VortexSystem {
        let system = VortexSystem(tags: ["circle"])
        system.position = [0.5, 0]
        system.speed = 0.5
        system.speedVariation = 0.25
        system.lifespan = 3
        system.shape = .box(width: 1, height: 0)
        system.angle = .degrees(180)
        system.angleRange = .degrees(20)
        system.size = 0.25
        system.sizeVariation = 0.5
        return system
    }
}

注意

除非你专门使用 yourSystem.makeUniqueCopy() 请求复制,否则 VortexView 不会复制你提供的粒子系统。 这允许你创建一次粒子系统并在多个地方重复使用它,而不会丢失其状态。

程序化粒子控制

虽然许多粒子系统不断发射粒子,但这不是必需的——你也可以根据需要创建爆发的粒子,例如,用户按下按钮时发射的彩屑炮。

这遵循与 SwiftUI 中类似的方法,例如 ScrollViewScrollViewReader:将你的 VortexView 包装在 VortexViewReader 中,后者会传递给你一个 VortexProxy 对象,该对象能够操作它找到的第一个粒子系统。

例如,这使用了内置的 .confetti 效果,然后使用 Vortex 代理对象根据需要触发粒子爆发

VortexViewReader { proxy in
    VortexView(.confetti) {
        Rectangle()
            .fill(.white)
            .frame(width: 16, height: 16)
            .tag("square")

        Circle()
            .fill(.white)
            .frame(width: 16)
            .tag("circle")
    }

    Button("Burst", action: proxy.burst)
}

你还可以使用代理的 attractTo() 方法使粒子朝向或远离特定点移动,该点以屏幕坐标指定。 确切的行为取决于你分配给粒子系统的 attractionStrength 属性的值:正值朝向你的吸引点移动,而负值则远离。

提示

使用 nil 作为参数调用 attractTo() 以清除吸引点。

二级系统

Vortex 更高级的功能之一是能够创建二级粒子系统——对于一个系统中的每个粒子,创建一个新的粒子系统。 这可以创建多阶段效果,例如烟花:一个粒子向上发射,在飞行时发射火花,然后在死亡时爆炸成彩色。

重要

当创建包含二级系统的粒子系统时,主系统和二级系统都可以拥有自己的标签集。 但是,在创建 ParticleView 时,你必须提供所有系统的所有标签。

创建自定义粒子系统

VortexSystem 的初始化程序采用各种配置选项来控制你的粒子系统的行为方式。 除一个之外,所有这些都具有合理的默认值,使你可以快速入门并动态调整内容。

详情(点击展开)

VortexSystem 初始化程序的参数为

其中大多数是内置类型,但有两个值得额外解释。

首先,Shape 允许你从一系列形状发射粒子:单点、直线、圆等等。 例如,这在可用空间中以水平线发射粒子

.box(width: 1, height: 0)

这在可用空间的一半大小的椭圆中创建粒子

.ellipse(radius: 0.5)

其次,ColorMode 使你可以精细地控制颜色如何在 Vortex 中工作。 新粒子系统的默认值为 .single(.white),这意味着所有粒子都是白色创建的。 但是,你可以创建一系列静态颜色的粒子,如下所示

.random(.red, .white, .blue)

你还可以创建颜色渐变,其中粒子会随着年龄的增长而改变颜色。 例如,这使粒子开始为白色,然后变为红色,然后逐渐消失

.ramp(.white, .red, .clear)

为了获得最大的控制,你可以使用*随机渐变*,其中每个粒子系统都会选择一个不同的渐变供粒子在老化时使用。 例如,这使得一些粒子开始为红色然后逐渐消失,而另一些粒子开始为蓝色然后逐渐消失

.randomRamp([.red, .clear], [.blue, .clear])

由于 Vortex 使用这些颜色模式来动态地重新着色你的粒子,因此建议在使用 SwiftUI 的原生形状(例如 RectangleCircle)时指定 .fill(.white),以确保可以正确地重新着色粒子。

内置预设

Vortex 提供了一系列内置预设来创建常见效果,也可以作为你自己的创作的起点。

详情(点击展开)

彩屑

.confetti 预设创建一个彩屑效果,其中视图在爆发发生时飞出。 这意味着使用 VortexViewReader 来访问 Vortex 代理,如下所示

VortexViewReader { proxy in
    VortexView(.confetti) {
        Rectangle()
            .fill(.white)
            .frame(width: 16, height: 16)
            .tag("square")
        
        Circle()
            .fill(.white)
            .frame(width: 16)
            .tag("circle")
    }
    
    Button("Burst", action: proxy.burst)
}

火焰

.fire 预设创建一个火焰效果。 当你的粒子具有柔和的边缘并使用 .plusLighter 混合模式时,这会更好,如下所示

VortexView(.fire) {
    Circle()
        .fill(.white)
        .frame(width: 32)
        .blur(radius: 3)
        .blendMode(.plusLighter)
        .tag("circle")
}

萤火虫

.fireflies 预设创建向上放大并逐渐消失的黄色发光点。 当你的粒子具有柔和的边缘时,这会更好,如下所示

VortexView(.fireflies) {
    Circle()
        .fill(.white)
        .frame(width: 32)
        .blur(radius: 3)
        .blendMode(.plusLighter)
        .tag("circle")
}

烟花

.fireworks 预设创建一个三阶段粒子效果来模拟爆炸的烟花。 每个烟花都是一个粒子,并且在向上飞行时还会发射新的“火花”粒子。 当烟花粒子被销毁时,它会产生一系列颜色的爆炸效果。

VortexView(.fireworks) {
    Circle()
        .fill(.white)
        .frame(width: 32)
        .blur(radius: 5)
        .blendMode(.plusLighter)
        .tag("circle")
}

魔法

.magic 预设创建一个简单的粒子环,这些粒子在逐渐消失时向外飞出。 使用此仓库的 Assets 文件夹中包含的“sparkle”图像效果最佳,但你可以使用任何其他你喜欢的图像或形状。

VortexView(.magic) {
    Image(.sparkle)
        .blendMode(.plusLighter)
        .tag("sparkle")
}

.rain 预设通过根据雨的速度拉伸你的视图来创建降雨系统

VortexView(.rain) {
    Circle()
        .fill(.white)
        .frame(width: 32)
        .tag("circle")
}

.smoke 预设创建一个从深灰色到黑色的烟雾效果。 当你的视图稍大一些并且具有柔和的边缘时,这会更好

VortexView(.smoke) {
    Circle()
        .fill(.white)
        .frame(width: 64)
        .blur(radius: 10)
        .tag("circle")
}

.snow 预设创建一个飘落的雪花效果。 当你的视图具有柔和的边缘时,这会更好,如下所示

VortexView(.snow) {
    Circle()
        .fill(.white)
        .frame(width: 24)
        .blur(radius: 5)
        .tag("circle")
}

火花

.spark 预设创建一个间歇性的火花效果,其中火花飞出一段时间,然后暂停,然后再次飞出,等等。

VortexView(.spark) {
    Circle()
        .fill(.white)
        .frame(width: 16)
        .tag("circle")
}

飞溅

.splash 预设包含雨滴飞溅效果,就像雨水击打地面一样。它与 .rain 预设结合使用效果最佳,例如:

ZStack {
    VortexView(.rain) {
        Circle()
            .fill(.white)
            .frame(width: 32)
            .tag("circle")
    }

    VortexView(.splash) {
        Circle()
            .fill(.white)
            .frame(width: 16, height: 16)
            .tag("circle")
    }
}

贡献

我欢迎所有贡献,无论是添加新的粒子系统预设、修复现有代码、添加注释还是改进此README – 欢迎所有人!

许可证

MIT 许可证。

版权所有 (c) 2024 Paul Hudson。

特此授予任何人免费获得本软件及相关文档文件(“软件”)副本的许可,不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向其提供本软件的人员这样做,但须符合以下条件:

上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。

本软件按“原样”提供,不作任何形式的明示或暗示保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为或其他方面,由本软件或本软件的使用或其他交易引起或与之相关。

Vortex 由 Paul Hudson 制作,他撰写了 Hacking with Swift 上的免费 Swift 教程。它根据 MIT 许可证提供,该许可证允许商业用途、修改、分发和私人用途。

Hacking with Swift+ logo

 

Hacking with Swift logo
一个 Hacking with Swift 项目