在 SwiftUI 视图中显示粒子发射器
Display particle emitter in SwiftUI View
尝试使用 SKScene 在视图中显示粒子发射器 spritekit 文件。
当前代码
struct ContentView: View {
var scene: SKScene {
let scene = SKScene(fileNamed: "magicSparkles")!
scene.size = CGSize(width: 400, height: 400)
scene.scaleMode = .fill
return scene
}
var body: some View {
VStack {
Text("Hello, World!")
.padding()
SpriteView(scene: scene)
.frame(width: 400, height: 400)
.edgesIgnoringSafeArea(.all)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
每当我尝试这样做时,模拟器都会抛出错误。
Moodie2 WatchKit Extension crashed due to an uncaught exception NSInvalidArgumentException. Reason: -[SKEmitterNode setScaleMode:]: unrecognized selector sent to instance 0x600003e981c0.
尝试不使用 SKScene(fileNamed: "magicSparkles"),将 SKScene 替换为 SKEmitterNode。不确定代码的其余部分是否 运行 正确
我对这个问题有部分答案,虽然它有一个我一直无法在手表上解决的问题。我在 iOS 设备上将 Spritekit 与 SwiftUI 结合使用,但从未在 watchOS 上使用过。我了解到的第一件事是 func didMove()
在 watchOS 上不存在,所以你必须使用 func sceneDidLoad()
来实现。以下代码将在手表上放置一个发射器:
import SwiftUI
import SpriteKit
struct ContentView: View {
var scene = EmitterScene()
var body: some View {
GeometryReader { geometry in
SpriteView(scene: scene)
}
}
}
class EmitterScene: SKScene {
override func sceneDidLoad() {
if let emitter = SKEmitterNode(fileNamed: "magicSparkles"){
emitter.position = CGPoint(x: frame.width / 2, y: frame.height / 2)
emitter.zPosition = -1
addChild(emitter)
}
}
}
我遇到的问题是发射器粒子显示不正确。它们太大了,你必须调整发射器以使其足够密集以使其定期显示,但它们似乎被放大到与表盘本身几乎相同的大小。我不知道如何解决这个问题。
所以有两件事:
- SpriteKit 内容不显示在 Xcode 预览中,仅在模拟器应用程序或设备上显示,供参考!
- 您只需继续将粒子添加到 SpriteKit 场景并将其放置在您的视图中,而不仅仅是一个发射器。
代码(忽略花形):
import SwiftUI
import SpriteKit
struct flowerhshape: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
let width = rect.size.width
let height = rect.size.height
path.move(to: CGPoint(x: 0, y: 0.66071*height))
path.addCurve(to: CGPoint(x: 0.19416*width, y: 0.83929*height), control1: CGPoint(x: 0, y: 0.75929*height), control2: CGPoint(x: 0.08698*width, y: 0.83929*height))
path.addCurve(to: CGPoint(x: 0.30444*width, y: 0.80786*height), control1: CGPoint(x: 0.23532*width, y: 0.83929*height), control2: CGPoint(x: 0.2726*width, y: 0.82786*height))
path.addLine(to: CGPoint(x: 0.30288*width, y: 0.82143*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: height), control1: CGPoint(x: 0.30288*width, y: 0.92*height), control2: CGPoint(x: 0.38987*width, y: height))
path.addCurve(to: CGPoint(x: 0.6912*width, y: 0.82143*height), control1: CGPoint(x: 0.60422*width, y: height), control2: CGPoint(x: 0.6912*width, y: 0.92*height))
path.addLine(to: CGPoint(x: 0.68965*width, y: 0.80786*height))
path.addCurve(to: CGPoint(x: 0.79993*width, y: 0.83929*height), control1: CGPoint(x: 0.72071*width, y: 0.82786*height), control2: CGPoint(x: 0.75876*width, y: 0.83929*height))
path.addCurve(to: CGPoint(x: 0.99409*width, y: 0.66071*height), control1: CGPoint(x: 0.9071*width, y: 0.83929*height), control2: CGPoint(x: 0.99409*width, y: 0.75929*height))
path.addCurve(to: CGPoint(x: 0.88302*width, y: 0.5*height), control1: CGPoint(x: 0.99409*width, y: 0.58929*height), control2: CGPoint(x: 0.94826*width, y: 0.52857*height))
path.addCurve(to: CGPoint(x: 0.99409*width, y: 0.33929*height), control1: CGPoint(x: 0.94826*width, y: 0.47143*height), control2: CGPoint(x: 0.99409*width, y: 0.41071*height))
path.addCurve(to: CGPoint(x: 0.79993*width, y: 0.16071*height), control1: CGPoint(x: 0.99409*width, y: 0.24071*height), control2: CGPoint(x: 0.9071*width, y: 0.16071*height))
path.addCurve(to: CGPoint(x: 0.68965*width, y: 0.19214*height), control1: CGPoint(x: 0.75876*width, y: 0.16071*height), control2: CGPoint(x: 0.72149*width, y: 0.17214*height))
path.addLine(to: CGPoint(x: 0.6912*width, y: 0.17857*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0), control1: CGPoint(x: 0.6912*width, y: 0.08*height), control2: CGPoint(x: 0.60422*width, y: 0))
path.addCurve(to: CGPoint(x: 0.30288*width, y: 0.17857*height), control1: CGPoint(x: 0.38987*width, y: 0), control2: CGPoint(x: 0.30288*width, y: 0.08*height))
path.addLine(to: CGPoint(x: 0.30444*width, y: 0.19214*height))
path.addCurve(to: CGPoint(x: 0.19416*width, y: 0.16071*height), control1: CGPoint(x: 0.27337*width, y: 0.17214*height), control2: CGPoint(x: 0.23532*width, y: 0.16071*height))
path.addCurve(to: CGPoint(x: 0, y: 0.33929*height), control1: CGPoint(x: 0.08698*width, y: 0.16071*height), control2: CGPoint(x: 0, y: 0.24071*height))
path.addCurve(to: CGPoint(x: 0.11106*width, y: 0.5*height), control1: CGPoint(x: 0, y: 0.41071*height), control2: CGPoint(x: 0.04582*width, y: 0.47143*height))
path.addCurve(to: CGPoint(x: 0, y: 0.66071*height), control1: CGPoint(x: 0.04582*width, y: 0.52857*height), control2: CGPoint(x: 0, y: 0.58929*height))
path.closeSubpath()
path.move(to: CGPoint(x: 0.6912*width, y: 0.5*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0.32143*height), control1: CGPoint(x: 0.6912*width, y: 0.40143*height), control2: CGPoint(x: 0.60422*width, y: 0.32143*height))
path.addCurve(to: CGPoint(x: 0.30288*width, y: 0.5*height), control1: CGPoint(x: 0.38987*width, y: 0.32143*height), control2: CGPoint(x: 0.30288*width, y: 0.40143*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0.67857*height), control1: CGPoint(x: 0.30288*width, y: 0.59857*height), control2: CGPoint(x: 0.38987*width, y: 0.67857*height))
path.addCurve(to: CGPoint(x: 0.6912*width, y: 0.5*height), control1: CGPoint(x: 0.60422*width, y: 0.67857*height), control2: CGPoint(x: 0.6912*width, y: 0.59857*height))
path.closeSubpath()
return path
}
}
struct ContentView: View {
var scene: SKScene {
let scene = SKScene(fileNamed: "MyScene")!
scene.scaleMode = .resizeFill
return scene
}
var body: some View {
VStack (alignment: .center, spacing: 4) {
SpriteView(scene: scene)
.aspectRatio(contentMode: .fill)
.frame(width: 120, height: 120, alignment: .top)
.rotationEffect(.degrees(180))
// .withAnimation(Animation.linear(duration: 1).repeatForever())
.clipShape(flowerhshape())
Text("Honor thy error as a hidden intention")
.font(.caption2)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
.frame(alignment: .top)
}
.padding(.top, 12.0)
.frame(alignment: .bottom)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
尝试使用 SKScene 在视图中显示粒子发射器 spritekit 文件。
当前代码
struct ContentView: View {
var scene: SKScene {
let scene = SKScene(fileNamed: "magicSparkles")!
scene.size = CGSize(width: 400, height: 400)
scene.scaleMode = .fill
return scene
}
var body: some View {
VStack {
Text("Hello, World!")
.padding()
SpriteView(scene: scene)
.frame(width: 400, height: 400)
.edgesIgnoringSafeArea(.all)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
每当我尝试这样做时,模拟器都会抛出错误。
Moodie2 WatchKit Extension crashed due to an uncaught exception NSInvalidArgumentException. Reason: -[SKEmitterNode setScaleMode:]: unrecognized selector sent to instance 0x600003e981c0.
尝试不使用 SKScene(fileNamed: "magicSparkles"),将 SKScene 替换为 SKEmitterNode。不确定代码的其余部分是否 运行 正确
我对这个问题有部分答案,虽然它有一个我一直无法在手表上解决的问题。我在 iOS 设备上将 Spritekit 与 SwiftUI 结合使用,但从未在 watchOS 上使用过。我了解到的第一件事是 func didMove()
在 watchOS 上不存在,所以你必须使用 func sceneDidLoad()
来实现。以下代码将在手表上放置一个发射器:
import SwiftUI
import SpriteKit
struct ContentView: View {
var scene = EmitterScene()
var body: some View {
GeometryReader { geometry in
SpriteView(scene: scene)
}
}
}
class EmitterScene: SKScene {
override func sceneDidLoad() {
if let emitter = SKEmitterNode(fileNamed: "magicSparkles"){
emitter.position = CGPoint(x: frame.width / 2, y: frame.height / 2)
emitter.zPosition = -1
addChild(emitter)
}
}
}
我遇到的问题是发射器粒子显示不正确。它们太大了,你必须调整发射器以使其足够密集以使其定期显示,但它们似乎被放大到与表盘本身几乎相同的大小。我不知道如何解决这个问题。
所以有两件事:
- SpriteKit 内容不显示在 Xcode 预览中,仅在模拟器应用程序或设备上显示,供参考!
- 您只需继续将粒子添加到 SpriteKit 场景并将其放置在您的视图中,而不仅仅是一个发射器。
代码(忽略花形):
import SwiftUI
import SpriteKit
struct flowerhshape: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
let width = rect.size.width
let height = rect.size.height
path.move(to: CGPoint(x: 0, y: 0.66071*height))
path.addCurve(to: CGPoint(x: 0.19416*width, y: 0.83929*height), control1: CGPoint(x: 0, y: 0.75929*height), control2: CGPoint(x: 0.08698*width, y: 0.83929*height))
path.addCurve(to: CGPoint(x: 0.30444*width, y: 0.80786*height), control1: CGPoint(x: 0.23532*width, y: 0.83929*height), control2: CGPoint(x: 0.2726*width, y: 0.82786*height))
path.addLine(to: CGPoint(x: 0.30288*width, y: 0.82143*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: height), control1: CGPoint(x: 0.30288*width, y: 0.92*height), control2: CGPoint(x: 0.38987*width, y: height))
path.addCurve(to: CGPoint(x: 0.6912*width, y: 0.82143*height), control1: CGPoint(x: 0.60422*width, y: height), control2: CGPoint(x: 0.6912*width, y: 0.92*height))
path.addLine(to: CGPoint(x: 0.68965*width, y: 0.80786*height))
path.addCurve(to: CGPoint(x: 0.79993*width, y: 0.83929*height), control1: CGPoint(x: 0.72071*width, y: 0.82786*height), control2: CGPoint(x: 0.75876*width, y: 0.83929*height))
path.addCurve(to: CGPoint(x: 0.99409*width, y: 0.66071*height), control1: CGPoint(x: 0.9071*width, y: 0.83929*height), control2: CGPoint(x: 0.99409*width, y: 0.75929*height))
path.addCurve(to: CGPoint(x: 0.88302*width, y: 0.5*height), control1: CGPoint(x: 0.99409*width, y: 0.58929*height), control2: CGPoint(x: 0.94826*width, y: 0.52857*height))
path.addCurve(to: CGPoint(x: 0.99409*width, y: 0.33929*height), control1: CGPoint(x: 0.94826*width, y: 0.47143*height), control2: CGPoint(x: 0.99409*width, y: 0.41071*height))
path.addCurve(to: CGPoint(x: 0.79993*width, y: 0.16071*height), control1: CGPoint(x: 0.99409*width, y: 0.24071*height), control2: CGPoint(x: 0.9071*width, y: 0.16071*height))
path.addCurve(to: CGPoint(x: 0.68965*width, y: 0.19214*height), control1: CGPoint(x: 0.75876*width, y: 0.16071*height), control2: CGPoint(x: 0.72149*width, y: 0.17214*height))
path.addLine(to: CGPoint(x: 0.6912*width, y: 0.17857*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0), control1: CGPoint(x: 0.6912*width, y: 0.08*height), control2: CGPoint(x: 0.60422*width, y: 0))
path.addCurve(to: CGPoint(x: 0.30288*width, y: 0.17857*height), control1: CGPoint(x: 0.38987*width, y: 0), control2: CGPoint(x: 0.30288*width, y: 0.08*height))
path.addLine(to: CGPoint(x: 0.30444*width, y: 0.19214*height))
path.addCurve(to: CGPoint(x: 0.19416*width, y: 0.16071*height), control1: CGPoint(x: 0.27337*width, y: 0.17214*height), control2: CGPoint(x: 0.23532*width, y: 0.16071*height))
path.addCurve(to: CGPoint(x: 0, y: 0.33929*height), control1: CGPoint(x: 0.08698*width, y: 0.16071*height), control2: CGPoint(x: 0, y: 0.24071*height))
path.addCurve(to: CGPoint(x: 0.11106*width, y: 0.5*height), control1: CGPoint(x: 0, y: 0.41071*height), control2: CGPoint(x: 0.04582*width, y: 0.47143*height))
path.addCurve(to: CGPoint(x: 0, y: 0.66071*height), control1: CGPoint(x: 0.04582*width, y: 0.52857*height), control2: CGPoint(x: 0, y: 0.58929*height))
path.closeSubpath()
path.move(to: CGPoint(x: 0.6912*width, y: 0.5*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0.32143*height), control1: CGPoint(x: 0.6912*width, y: 0.40143*height), control2: CGPoint(x: 0.60422*width, y: 0.32143*height))
path.addCurve(to: CGPoint(x: 0.30288*width, y: 0.5*height), control1: CGPoint(x: 0.38987*width, y: 0.32143*height), control2: CGPoint(x: 0.30288*width, y: 0.40143*height))
path.addCurve(to: CGPoint(x: 0.49704*width, y: 0.67857*height), control1: CGPoint(x: 0.30288*width, y: 0.59857*height), control2: CGPoint(x: 0.38987*width, y: 0.67857*height))
path.addCurve(to: CGPoint(x: 0.6912*width, y: 0.5*height), control1: CGPoint(x: 0.60422*width, y: 0.67857*height), control2: CGPoint(x: 0.6912*width, y: 0.59857*height))
path.closeSubpath()
return path
}
}
struct ContentView: View {
var scene: SKScene {
let scene = SKScene(fileNamed: "MyScene")!
scene.scaleMode = .resizeFill
return scene
}
var body: some View {
VStack (alignment: .center, spacing: 4) {
SpriteView(scene: scene)
.aspectRatio(contentMode: .fill)
.frame(width: 120, height: 120, alignment: .top)
.rotationEffect(.degrees(180))
// .withAnimation(Animation.linear(duration: 1).repeatForever())
.clipShape(flowerhshape())
Text("Honor thy error as a hidden intention")
.font(.caption2)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
.frame(alignment: .top)
}
.padding(.top, 12.0)
.frame(alignment: .bottom)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}