Swift 我能';t将UIBezierPath添加到CAEmitterCell';s内容变量
我无法将我用UIBezierPath绘制的图标添加到CAEmitterCell。我想知道图标是否没有画出来?运行应用程序时,ShapeView不工作。但是,当您正常使用ShapeView时,您可能会发现它可以正常工作 那么我有机会将UIBezierPath转换为图像吗 在不转换为图像的情况下,它真的可以完成吗 使用Swift 我能';t将UIBezierPath添加到CAEmitterCell';s内容变量,swift,swiftui,uibezierpath,caemitterlayer,Swift,Swiftui,Uibezierpath,Caemitterlayer,我无法将我用UIBezierPath绘制的图标添加到CAEmitterCell。我想知道图标是否没有画出来?运行应用程序时,ShapeView不工作。但是,当您正常使用ShapeView时,您可能会发现它可以正常工作 那么我有机会将UIBezierPath转换为图像吗 在不转换为图像的情况下,它真的可以完成吗 使用 struct GameView: View { .... let playerBounds = UIBezierPath.calculateBounds(p
struct GameView: View {
....
let playerBounds = UIBezierPath.calculateBounds(paths: [.none, .playerX, .playerO])
var body: some View {
ZStack {
ParticleEffectView(particleImages: [ShapeView(bezier: .playerX, pathBounds: playerBounds), ShapeView(bezier: .playerO, pathBounds: playerBounds)])
....
}
}
}
形状视图
struct ShapeView: Shape {
let bezier: UIBezierPath
let pathBounds: CGRect
func path(in rect: CGRect) -> Path {
let pointScale = (rect.width >= rect.height) ? max(pathBounds.height, pathBounds.width) : min(pathBounds.height, pathBounds.width)
let pointTransform = CGAffineTransform(scaleX: 1/pointScale, y: 1/pointScale)
let path = Path(bezier.cgPath).applying(pointTransform)
let multiplier = min(rect.width, rect.height)
let transform = CGAffineTransform(scaleX: multiplier, y: multiplier)
return path.applying(transform)
}
}
struct ParticleEffectView: UIViewRepresentable {
var particleImages: [ShapeView]
func makeUIView(context: Context) -> UIView {
let host = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
let particlesLayer = CAEmitterLayer()
particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
host.layer.insertSublayer(particlesLayer, at: 0)
host.layer.masksToBounds = true
host.insetsLayoutMarginsFromSafeArea = false
particlesLayer.backgroundColor = .none
particlesLayer.emitterShape = .circle
particlesLayer.emitterPosition = CGPoint(x: 509.4, y: 707.7)
particlesLayer.emitterSize = CGSize(width: 1648.0, height: 1112.0)
particlesLayer.emitterMode = .outline
particlesLayer.renderMode = .backToFront
particlesLayer.emitterCells = prepareParticeCell(particles: particleImages)
return host
}
func prepareParticeCell(particles: [ShapeView]) -> [CAEmitterCell] {
var arrayParticleCell: [CAEmitterCell] = [CAEmitterCell]()
for particleItem in particles {
let particleCell: CAEmitterCell = CAEmitterCell()
particleCell.contents = particleItem
particleCell.name = "XO"
particleCell.birthRate = 1
particleCell.lifetime = 74.5
particleCell.velocityRange = 0.0
particleCell.velocity = 79.0
particleCell.xAcceleration = 0.0
particleCell.yAcceleration = 0.0
particleCell.emissionLatitude = 1*6.0 * (.pi / 180)
particleCell.emissionLongitude = -105.0 * (.pi / 180)
particleCell.emissionRange = 360.0 * (.pi / 180.0)
particleCell.spin = -65.6 * (.pi / 180.0)
particleCell.spinRange = 314.2 * (.pi / 180.0)
particleCell.scale = 0.010
particleCell.scaleRange = 0.01
particleCell.scaleSpeed = 0.02
particleCell.alphaRange = 0.0
particleCell.alphaSpeed = 0.47
particleCell.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
arrayParticleCell.append(particleCell)
}
return arrayParticleCell
}
func updateUIView(_ uiView: UIView, context: Context) {
uiView.insetsLayoutMarginsFromSafeArea = false
}
}
UIBezier路径
extension UIBezierPath {
static func calculateBounds(paths: [UIBezierPath]) -> CGRect {
let myPaths = UIBezierPath()
for path in paths {
myPaths.append(path)
}
return (myPaths.bounds)
}
static var playerX: UIBezierPath {
let shape = UIBezierPath()
shape.move(to: CGPoint(x: 48.04, y: 33.28))
shape.addLine(to: CGPoint(x: 62.04, y: 19.28))
shape.addCurve(to: CGPoint(x: 62.04, y: 3.96), controlPoint1: CGPoint(x: 66.28, y: 15.05), controlPoint2: CGPoint(x: 66.28, y: 8.19))
shape.addCurve(to: CGPoint(x: 46.72, y: 3.96), controlPoint1: CGPoint(x: 57.81, y: -0.27), controlPoint2: CGPoint(x: 50.96, y: -0.27))
shape.addLine(to: CGPoint(x: 32.72, y: 17.96))
shape.addLine(to: CGPoint(x: 18.71, y: 3.96))
shape.addCurve(to: CGPoint(x: 3.39, y: 3.96), controlPoint1: CGPoint(x: 14.48, y: -0.27), controlPoint2: CGPoint(x: 7.62, y: -0.27))
shape.addCurve(to: CGPoint(x: 3.39, y: 19.28), controlPoint1: CGPoint(x: -0.84, y: 8.18), controlPoint2: CGPoint(x: -0.84, y: 15.05))
shape.addLine(to: CGPoint(x: 17.4, y: 33.28))
shape.addLine(to: CGPoint(x: 3.39, y: 47.29))
shape.addCurve(to: CGPoint(x: 3.39, y: 62.61), controlPoint1: CGPoint(x: -0.84, y: 51.52), controlPoint2: CGPoint(x: -0.84, y: 58.38))
shape.addCurve(to: CGPoint(x: 18.71, y: 62.61), controlPoint1: CGPoint(x: 7.62, y: 66.84), controlPoint2: CGPoint(x: 14.48, y: 66.84))
shape.addLine(to: CGPoint(x: 32.72, y: 48.6))
shape.addLine(to: CGPoint(x: 46.72, y: 62.61))
shape.addCurve(to: CGPoint(x: 62.04, y: 62.61), controlPoint1: CGPoint(x: 50.96, y: 66.84), controlPoint2: CGPoint(x: 57.81, y: 66.84))
shape.addCurve(to: CGPoint(x: 62.04, y: 47.29), controlPoint1: CGPoint(x: 66.28, y: 58.38), controlPoint2: CGPoint(x: 66.28, y: 51.52))
shape.addLine(to: CGPoint(x: 48.04, y: 33.28))
shape.close()
return shape
}
static var playerO: UIBezierPath {
let shape = UIBezierPath()
shape.move(to: CGPoint(x: 32.5, y: 0))
shape.addCurve(to: CGPoint(x: 0, y: 32.5), controlPoint1: CGPoint(x: 14.55, y: 0), controlPoint2: CGPoint(x: 0, y: 14.55))
shape.addCurve(to: CGPoint(x: 32.5, y: 65), controlPoint1: CGPoint(x: 0, y: 50.45), controlPoint2: CGPoint(x: 14.55, y: 65))
shape.addCurve(to: CGPoint(x: 65, y: 32.5), controlPoint1: CGPoint(x: 50.45, y: 65), controlPoint2: CGPoint(x: 65, y: 50.45))
shape.addCurve(to: CGPoint(x: 32.5, y: 0), controlPoint1: CGPoint(x: 65, y: 14.55), controlPoint2: CGPoint(x: 50.45, y: 0))
shape.close()
shape.move(to: CGPoint(x: 32.01, y: 49.24))
shape.addCurve(to: CGPoint(x: 15.76, y: 32.99), controlPoint1: CGPoint(x: 23.03, y: 49.24), controlPoint2: CGPoint(x: 15.76, y: 41.97))
shape.addCurve(to: CGPoint(x: 32.01, y: 16.74), controlPoint1: CGPoint(x: 15.76, y: 24.02), controlPoint2: CGPoint(x: 23.03, y: 16.74))
shape.addCurve(to: CGPoint(x: 48.26, y: 32.99), controlPoint1: CGPoint(x: 40.98, y: 16.74), controlPoint2: CGPoint(x: 48.26, y: 24.02))
shape.addCurve(to: CGPoint(x: 32.01, y: 49.24), controlPoint1: CGPoint(x: 48.26, y: 41.97), controlPoint2: CGPoint(x: 40.98, y: 49.24))
shape.close()
return shape
}
static var none: UIBezierPath {
let shape = UIBezierPath()
return shape
}
}
粒子效果视图
struct ShapeView: Shape {
let bezier: UIBezierPath
let pathBounds: CGRect
func path(in rect: CGRect) -> Path {
let pointScale = (rect.width >= rect.height) ? max(pathBounds.height, pathBounds.width) : min(pathBounds.height, pathBounds.width)
let pointTransform = CGAffineTransform(scaleX: 1/pointScale, y: 1/pointScale)
let path = Path(bezier.cgPath).applying(pointTransform)
let multiplier = min(rect.width, rect.height)
let transform = CGAffineTransform(scaleX: multiplier, y: multiplier)
return path.applying(transform)
}
}
struct ParticleEffectView: UIViewRepresentable {
var particleImages: [ShapeView]
func makeUIView(context: Context) -> UIView {
let host = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
let particlesLayer = CAEmitterLayer()
particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
host.layer.insertSublayer(particlesLayer, at: 0)
host.layer.masksToBounds = true
host.insetsLayoutMarginsFromSafeArea = false
particlesLayer.backgroundColor = .none
particlesLayer.emitterShape = .circle
particlesLayer.emitterPosition = CGPoint(x: 509.4, y: 707.7)
particlesLayer.emitterSize = CGSize(width: 1648.0, height: 1112.0)
particlesLayer.emitterMode = .outline
particlesLayer.renderMode = .backToFront
particlesLayer.emitterCells = prepareParticeCell(particles: particleImages)
return host
}
func prepareParticeCell(particles: [ShapeView]) -> [CAEmitterCell] {
var arrayParticleCell: [CAEmitterCell] = [CAEmitterCell]()
for particleItem in particles {
let particleCell: CAEmitterCell = CAEmitterCell()
particleCell.contents = particleItem
particleCell.name = "XO"
particleCell.birthRate = 1
particleCell.lifetime = 74.5
particleCell.velocityRange = 0.0
particleCell.velocity = 79.0
particleCell.xAcceleration = 0.0
particleCell.yAcceleration = 0.0
particleCell.emissionLatitude = 1*6.0 * (.pi / 180)
particleCell.emissionLongitude = -105.0 * (.pi / 180)
particleCell.emissionRange = 360.0 * (.pi / 180.0)
particleCell.spin = -65.6 * (.pi / 180.0)
particleCell.spinRange = 314.2 * (.pi / 180.0)
particleCell.scale = 0.010
particleCell.scaleRange = 0.01
particleCell.scaleSpeed = 0.02
particleCell.alphaRange = 0.0
particleCell.alphaSpeed = 0.47
particleCell.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
arrayParticleCell.append(particleCell)
}
return arrayParticleCell
}
func updateUIView(_ uiView: UIView, context: Context) {
uiView.insetsLayoutMarginsFromSafeArea = false
}
}
当你说
particleCell.contents = particleItem
没有编译时错误,但在运行时也不会发生任何事情。这是因为发射器单元
contents
只能是一个CGImage(参见),而ShapeView显然不是CGImage。将内容
设置为CGImage以外的任何内容都不是错误,而是无效的,并且找出问题所在可能需要很长时间。我经常向苹果抱怨这一点。我可以将UIBezierPath转换为图像吗?您可以将UIBezierPath绘制到图像图形上下文中并提取图像。但在我看来,这是一个不同的问题。