我无法将 UIBezierPath 添加到 CAEmitterCell 的内容变量

问题描述

我无法将使用 UIBezierPath 绘制的图标添加到 CAEmitterCell。请问图标是不是画出来的?当我运行应用程序时,ShapeView 不起作用。但是,您可能会发现 ShapeView 在您正常使用时可以正常工作。

那么我有机会将 UIBezierPath 转换为图像吗?

不转图片真的可以吗?

使用

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)
    }
}

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,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,controlPoint1: CGPoint(x: 14.48,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),y: 51.52),y: 58.38))
        shape.addCurve(to: CGPoint(x: 18.71,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,controlPoint1: CGPoint(x: 50.96,controlPoint2: CGPoint(x: 57.81,y: 66.84))
        shape.addCurve(to: CGPoint(x: 62.04,y: 47.29),y: 58.38),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,controlPoint1: CGPoint(x: 50.45,controlPoint2: CGPoint(x: 65,y: 50.45))
        shape.addCurve(to: CGPoint(x: 32.5,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,controlPoint1: CGPoint(x: 40.98,controlPoint2: CGPoint(x: 48.26,y: 24.02))
        shape.addCurve(to: CGPoint(x: 32.01,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 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,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(参见 documentation)——而 ShapeView,很明显,不是 CGImage。将 contents 设置为 CGImage 以外的任何其他内容不是错误但无效,并且找出问题所在可能需要很长时间。我经常向 Apple 抱怨这个问题。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...