Core Animationのパーティクルシステム。 クリスマスストーリー





みなさんこんにちは!



クリスマスはもうなくなっていますが、その後、使用頻度の低いコアアニメーション機能を使用してユーザーにお祝いのムードを作成する方法についての興味深い話があります。 ロンドンの同僚アレクシスの記事の翻訳を共有しています。



クリスマスはいつも私にとって一年の中で一番好きな日です。 それは私たちの生活に多くの愛、笑い、幸福と魔法をもたらします。



私はスペインのテネリフェ島で生まれ育ちました。テネリフェ島はアフリカ沿岸の大西洋の真ん中にある日当たりの良い島です。 そして、私を信じてください、テネリフェ島のクリスマスはロンドンのクリスマスとは非常に異なっています。



私にとってロンドンに住んでいる利点の一つは、雪片の熟考でした。 ここで私は彼らを私の人生で初めて見ました。それは信じられないほど素晴らしかったです!



これを思い出して、クリスマスの少し前にオフィスで起こった興味深い話をあなたと分かち合うことにしました。その後、家族と休日を祝うためにテネリフェ島に行きました。



たまたま、私は次の説明を含む異常なタスクを1つ割り当てられました。







うーん、かなり面白い。 私たちは、iOSアプリケーションに雪の結晶のクリスマスアニメーションを追加したかったので、私は幸運なことに、それを作成しました。 しかし、どこから始めればいいのかわかりませんでした。



いつものように、スケッチファイルは必要なデザインでタスクに添付され、次のようになりました。







少なくとも必要なものは見ましたが、これらの雪片の振る舞いが完全にはわかりませんでした。 すべての詳細を明確にするために、デザイナーと話をしました。



私が疑ったように、彼らはすでにAfter Effectsで素晴らしいアニメーションを描いていました。



デザイナーは、アプリケーションを起動する既存のアニメーションに、上から降る雪片を追加したいことを私に説明しました(ロゴのサンタの帽子だけでなく、この記事で言及する価値のない写真の単純な置換でした)。



iOSでアプリケーションを起動するアニメーションは、入社後に追加されたように、 Lottieを使用して作成されたことを知っていました(詳細は記事Radek Cieciwaで確認できます)。 しかし、私はデザイナーに、雪片を表示するためのより簡単な解決策を見つけようとすると言いました(ロティを使用する必要はありません)-さまざまなアプローチを探り始めました。



同僚のラデクがBadoo向けに作成したアニメーションを次に示します。 申し分のない!







そして、私は雪片を追加しました。 私がそれをどのようにしたか知りたいですか? 以下に答えがあります。







パーティクルシステム



アニメーションに関するさまざまなドキュメントを読みながら、ゲームや映画では、こうした問題を解決するためにパーティクルシステムがよく使用されることを思い出しました。



ウィキペディアはこの概念を非常に正確に説明しています。



「パーティクルシステムは、明確な幾何学的境界(さまざまな雲、星雲、爆発、蒸気ジェット、ミサイルループ、煙、雪、雨など)を持たないオブジェクトを表すためにコンピューターグラフィックスで使用される方法です。 パーティクルシステムは、2次元グラフィックスと3次元グラフィックスの両方で実装できます。」


この手法は、1982年に「スタートレック2:カーンの怒り」で「ジェネシスエフェクト」を作成するために最初に使用されました。




パーティクルシステムは、パーティクルと呼ばれるポイント、ライン、画像などの1つ以上のグラフィックプリミティブで構成されます。 これらのパーティクルは、パーティクルシステムの一部であるエミッタによって作成および放出されます。



各パーティクルには、その動作に直接または間接的に影響し、描画方法を決定するパラメータのセットがあります。 粒子は、例えば液体の効果を作り出すために、同時に多数の異なる方向に移動できます。



システムからパーティクルが放出されると、アニメーションが有効になります。 システムは、パーティクルシステムの指定された領域内のランダムな場所にパーティクルを放出します。 円、長方形、球、箱、線、点など、さまざまな形式を取ります。



また、システムは、ジオメトリ、速度、その他のパラメータに影響を与えるパーティクルのプロパティも決定します。 異なるエミッタAPIには、同様のプロパティの異なる名前があります。



パーティクルがシステムから同時に放出されると、雨、火、雪のように見える見事なアニメーションが作成されます。







理論から実践へ



Appleはおそらくそのフレームワークの1つでパーティクルシステムの組み込みサポートを持っていると思いました。 そして、私の検索結果は、私が正しいことを示しています。



パーティクルシステムはCore Animationフレームワークの一部であり、 CAEmitterLayerおよびCAEmitterCellクラスで 詳しく説明されています



iOSでパーティクルシステムとサポートされているAPIについて必要なすべての情報を調べた後、自分の好きな部分、つまりアイデアの実装に進みました。



残念ながら、クリスマスは永遠ではないため、12月25日以降は雪片をリモートでオフにする機能が必要でした。



前述したように、アプリケーションの起動アニメーションはLottieを使用して実装されました。 つまり、既存のアニメーションとそのコードに影響を与えないように雪片を追加する方法を見つける必要がありました。これは、ソリューションをリリース後すぐに削除する必要があるためです。



これを行う非常に簡単な方法を見つけました-既存のアニメーションと背景の前に雪片を表示する新しい透明なUIViewを追加し、フラグを使用してその外観をリモートで制御しました。







上の画像は、最終的なソリューションで使用されたUIViewを示しています。



  1. 雪片を放出するパーティクルシステムを備えたUIView

  2. Lottieによって駆動されるアプリケーション起動アニメーションで使用されるUIView





この問題を解決した後、アニメーション化された雪片を生成するために、パーティクル放出のロジックを含むコンポーネントを作成する必要がありました。



手始めに、エミッターのコンテンツとして使用できる雪片の画像が必要でした。 それらはかなりシンプルなはずですよね?



各スノーフレークは普通の、またはぼやけた白い円でした。 Sketchで自分で作成しました。







実装の詳細



CAEmitterLayerは、パーティクルシステムを作成、アニメーション化、レンダリングする特別なCALayerです。 ジオメトリ、位置、描画モードなどを制御できます。



レイヤーを作成してアニメーションの開発を始めました。



snowEmitterLayer.emitterShape = CAEmitterLayerEmitterShape.line snowEmitterLayer.beginTime = CACurrentMediaTime() snowEmitterLayer.timeOffset = 10.0
      
      





変更する必要があるプロパティは3つだけです。





レイヤーが完成したので、2つの異なるエミッターを作成しました。雪片の方が重く、雪片の方が簡単です。



重い雪の場合、次のようにエミッターを設定します。



 let flakeEmitterCell = CAEmitterCell() flakeEmitterCell.contents = UIImage(named: "snowflake_dot")!.cgImage flakeEmitterCell.emissionRange = .pi flakeEmitterCell.lifetime = 20.0 flakeEmitterCell.birthRate = 30 flakeEmitterCell.scale = 0.15 flakeEmitterCell.scaleRange = 0.6 flakeEmitterCell.velocity = 30.0 flakeEmitterCell.velocityRange = 20 flakeEmitterCell.spin = -0.5 flakeEmitterCell.spinRange = 1.0 flakeEmitterCell.yAcceleration = 30.0 flakeEmitterCell.xAcceleration = 5.0
      
      





ご覧のとおり、私はかなりの数のプロパティを変更する必要がありました。それぞれのプロパティは、目的の効果を得るために非常に重要です。





また、軽い雪片を作成するために2番目のエミッターが必要でした。 2つの例外を除き、すべてのプロパティは変更されていません。





 let blurryFlakeEmitterCell = CAEmitterCell() blurryFlakeEmitterCell.contents = UIImage(named: "snowflake_blurry_dot")?.cgImage blurryFlakeEmitterCell.velocity = 40 //     
      
      





レイヤーとエミッターのみを接続できましたが、非常に簡単でした。



 snowEmitterLayer.emitterCells = [flakeEmitterCell, blurryFlakeEmitterCell] self.layer.addSublayer(snowEmitterLayer)
      
      





おわりに



私はすぐに、落ちてくる雪の結晶を含む作業バージョンを作成しました。 実装はかなり簡単で、既存のコードは変更しませんでした。 デザイナーに見せたところ、彼らは本当に気に入った。



適切なツールがあれば、パーティクルシステムアニメーションは非常に印象的で、比較的簡単に実装できます。



パーティクルシステムの詳細については、次のソースを参照してください。






All Articles