【问题标题】:How do I add a 'snow like' effect to a UIView如何向 UIView 添加“雪状”效果
【发布时间】:2016-03-02 11:24:04
【问题描述】:

我目前正在制作一个圣诞节应用程序,我希望它在屏幕上“下雪”。

到目前为止,我有这个代码:

Snow.swift

import Foundation
import UIKit

@IBDesignable
class Snow:UIView
{

    var viewHeight = CGFloat(0)
    /*
    required init(coder aDecoder: NSCoder) {
        //Initilse UIView
        super.init(coder: aDecoder)!
    }
    */

    override func drawRect(rect: CGRect) {
        let path = UIBezierPath(ovalInRect: rect)
        UIColor.whiteColor().setFill()
        path.fill()
    }
}

ViewController.swift

@IBDesignable
class ViewController: UIViewController {

    @IBInspectable var BgColor:UIColor = UIColor.whiteColor()

    var animator: UIDynamicAnimator? = nil;
    var gravity = UIGravityBehavior()


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = BgColor
        /*listSubviewsOfView(self.view)*/ /*Not needed to answer this*/
        var snow = Snow(frame: CGRect(x: 0, y: 0, width: 5, height: 5))
        snow.opaque = false
        self.view.addSubview(snow)

        animator = UIDynamicAnimator(referenceView:self.view);
        animator?.addBehavior(gravity)

        gravity.addItem(snow)
        let direction = CGVectorMake(0.0, 1.0)
        gravity.gravityDirection = direction
    }


    /*Not needed to solve this*/
    /*
    func listSubviewsOfView(views: UIView) {
        var index = 0
        let randomNumbers = [Int](1...24).shuffle()
        for view in views.subviews
        {
            if let _ = view.restorationIdentifier
            {
                view.setValue(String(Int(randomNumbers[index])), forKey: "updateText")
                index++
            }
            if index == randomNumbers.count {
                break
            }
        }
    }
    */

}

这是它目前的样子(在 iPhone 5 模拟器中)

如您所见,UIView 掉到屏幕底部的速度太快(像砖块而不是雪一样掉下来)。

我怎样才能让“雪”随着风的影响而下得更慢?

【问题讨论】:

标签: ios uiview core-graphics core-animation


【解决方案1】:

我会用一个 SKEmitterNode 来做到这一点。 SpriteKit 中还有一个图形编辑器,您可以在其中轻松创建雪景效果。这是一个简短的教程:enter link description here

【讨论】:

  • 我可以将它与单视图模板一起使用吗?
  • 我想是的,但从未尝试过。通常我会创建一个游戏模板:它带有一个 ViewController 和一个故事板,您可以在其中添加 UIViewElements
  • Sprite Kit 不能与 UIView 混合使用。
  • @RW。是的,它可以。 SKView 是一个 UIView 子类,具有关联的 SKScene
【解决方案2】:

使用 UIKitDynamics 的 UIGravityBehaviour 为对象设置动画。您可以使用 UIKitDynamics 轻松创建出色的动画

    snowView = UIView(frame: CGRect(x: 100, y: 100, width: 20, height: 20))
    snowView.backgroundColor = UIColor.blueColor()
    view.addSubview(snowView)

    animator = UIDynamicAnimator(referenceView: view)
    gravity = UIGravityBehavior(items: [snowView])
    animator.addBehavior(gravity)

    animator.addBehavior(collision)

    itemBehaviour = UIDynamicItemBehavior(items: [snowView])
    itemBehaviour.elasticity = 0.7
    animator.addBehavior(itemBehaviour)

查看此链接以供参考: http://www.sitepoint.com/using-uikit-dynamics-swift-animate-apps/

【讨论】:

    【解决方案3】:

    如果您当前没有使用 SpriteKit,那么使用 CAEmitterLayer 可能会更好,请参阅

    上的教程

    http://www.enharmonichq.com/tutorial-particle-systems-in-core-animation-with-caemitterlayer/

    这个想法是,您将在修道院视图的顶部添加一个发射器层,该发射器层与该视图的大小相同,顶部有一个线形发射器单元,用于发射雪花颗粒。

    粒子发射器支持随机放置和随机运动。 (雪花随着一些随机的左右运动飘落到地面。)

    【讨论】:

      【解决方案4】:

      我已经分享了所有的实现。但是你需要 flake.png 你可以通过谷歌找到。

      import UIKit
      import QuartzCore
      
      class ViewController: UIViewController {
      
        var snowView: SnowView!
      
        override func viewDidLoad() {
          super.viewDidLoad()
      
          //add the snow effect layer
          snowView = SnowView(frame: CGRect(x: -150, y:-100, width: 300, height: 50))
          let snowClipView = UIView(frame: CGRectOffset(view.frame, 0, 50))
          snowClipView.clipsToBounds = true
          snowClipView.addSubview(snowView)
          view.addSubview(snowClipView)
      
        }
      }
      
      
      import UIKit
      import QuartzCore
      
      class SnowView: UIView {
      
        override init(frame: CGRect) {
          super.init(frame: frame)
      
          let emitter = layer as! CAEmitterLayer
          emitter.emitterPosition = CGPoint(x: bounds.size.width / 2, y: 0)
          emitter.emitterSize = bounds.size
          emitter.emitterShape = kCAEmitterLayerRectangle
      
          let emitterCell = CAEmitterCell()
          emitterCell.contents = UIImage(named: "flake.png")!.CGImage
          emitterCell.birthRate = 200
          emitterCell.lifetime = 3.5
          emitterCell.color = UIColor.whiteColor().CGColor
          emitterCell.redRange = 0.0
          emitterCell.blueRange = 0.1
          emitterCell.greenRange = 0.0
          emitterCell.velocity = 10
          emitterCell.velocityRange = 350
          emitterCell.emissionRange = CGFloat(M_PI_2)
          emitterCell.emissionLongitude = CGFloat(-M_PI)
          emitterCell.yAcceleration = 70
          emitterCell.xAcceleration = 0
          emitterCell.scale = 0.33
          emitterCell.scaleRange = 1.25
          emitterCell.scaleSpeed = -0.25
          emitterCell.alphaRange = 0.5
          emitterCell.alphaSpeed = -0.15
      
          emitter.emitterCells = [emitterCell]
        }
      
        required init(coder aDecoder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
        }
      
        override class func layerClass() -> AnyClass {
          return CAEmitterLayer.self
        }
      
      }
      

      【讨论】:

      • 谢谢,但这在 swift 4.2 中运行存在一些问题
      猜你喜欢
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多