2013-03-04 5 views
9

私はObjective CのImpress.jsのsample presentationの2Dトランジションを再現しようとしています。具体的には、回転、パン、スケーリング - 今はスケーリングに焦点を当てています。メモリを大量に使用せずに遷移UILabelをスケールする方法は?

サンプルプレゼンテーションでは、「あなたのビッグアイズを視覚化する」 - >「小さなアイデア」のように、UILabelを「画面を通過する」ところまでスケールアップしようとしました。

これは私がこれまで試したものです:

UILabel *label = [[UILabel alloc] init]; 

label.text = @"Hello World!"; 
label.textColor = [UIColor blackColor]; 
label.font = [UIFont fontWithName:@"Arial" size:18.f]; 
[label sizeToFit]; 
label.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2); 
[self.view addSubview:label]; 

label.contentScaleFactor *= 80; 

[UIView animateWithDuration:5 animations:^{ 
    label.transform = CGAffineTransformScale(label.transform, 80, 80); 
}]; 

残念ながら、これはcontentScaleFactor、初期フォントサイズが何であるかに応じて、RAMの〜30〜60メガバイト程度食べます。 contentScaleFactorを大きくしないと、テキストがぼやけて見えます。フォントサイズを大きくすると、同じくらい多くのメモリを食べているようです。ここで

それはプロファイラに見えるものです:

enter image description here

そして、これは1つだけUILabelです。

レンダリングされるテキストの品質やトランジションを犠牲にすることなく、非常に多くのメモリを消費することなくこれを行う方法はありますか?

+0

とにかく、レイヤーをグループ化してトランスフォームする方法として、CATransformLayerを見てみましょう。 –

+0

UILabelをスケーリングした後のメモリ消費量に焦点を当てて質問を更新しました。前の質問はあまりにも広すぎる(そして閉じられた)。現在受け入れられている回答は素晴らしいですが、更新された質問の問題は解決しません。私はそれに別の賞金を与えたいが、私は別の500を落とす非常に小さな担当者を持っている。 – Luke

答えて

4

Project download link

https://github.com/yangmeyer/CPAnimationSequenceまたはこのライブラリ:あなたはこのライブラリを使用して、必要なアニメーションをチェーンことができます。あなたが説明したことばかりでなく、Impress.jsを使いこなすことから集めたものはすべて、コンテナビューに自由に移動できるUILabelsのセットに変形(ほとんど2D、3D)を適用することによって複製可能なようです。メインビュー。

はこれを行うには、私が作成したプロジェクトではなく、ラベルにフレームを渡すので、あなたのサイズ、中心点を通過し、余分なinit関数で「ImpressLabel」と題しUILabelのサブクラス、およびのためのCGFloatを使用していますラベルのZ軸上での回転。この変換はインスタンシエーション時にラベルに適用されるため、ラベルを設定すると、すでに指定された位置と変形の画面に表示されます。

次に、テキストを構成する限り、NSStringの代わりにNSAttributedStringというラベルを渡すことができます。これは、あなたはここで上記の二つのパラグラフの一例ですので、ラベル内の異なる単語が異なるサイズ、フォント、色、背景色などをすることができ、独立した文字列の異なる部分を変更することができます:今すぐ

ImpressLabel *label1 = [[ImpressLabel alloc] initWithSize:CGSizeMake(260.0f, 80.0f) andCenterPointInSuperview:CGPointMake(500.0f, 500.0f) andRotationInSuperview:0.0f andEndingScaleFactor:1.3]; 

NSMutableAttributedString *firstLabelAttributes = [[NSMutableAttributedString alloc] initWithString:@"then you should try\nimpress.js*\n* no rhyme intended"]; 

[firstLabelAttributes addAttribute:NSFontAttributeName 
          value:[UIFont systemFontOfSize:label1.font.pointSize - 2] 
          range:NSMakeRange(0, 19)]; 

[firstLabelAttributes addAttribute:NSFontAttributeName 
          value:[UIFont systemFontOfSize:label1.font.pointSize - 8] 
          range:NSMakeRange(firstLabelAttributes.string.length - 19, 19)]; 

[firstLabelAttributes addAttribute:NSFontAttributeName 
          value:[UIFont boldSystemFontOfSize:label1.font.pointSize + 14] 
          range:NSMakeRange(23, 11)]; 


[label1 setNumberOfLines:3]; 
[label1 setAttributedText:firstLabelAttributes]; 
[label1 setTextAlignment:NSTextAlignmentCenter]; 
[containmentView addSubview:label1]; 

、全体の操作の邪魔になります。上記のとおり、このサブクラスは各ラベルにタップジェスチャを追加します。タップが認識されると、いくつかのことが起こります。ラベルを含むビューは、スケールを調整してパン/バック/アウェイします。アニメーションが停止すると、選択したラベルが正しい向きで画面の中央に表示されるように、メインビューでアンカーポイントを回転して調整します。それからもちろん、これはすべて進行中ですが、選択されたラベルのアルファは1.0fに、残りのアルファは0.25fに下げられます。

- (void)tapForRotationDetected:(UITapGestureRecognizer *)sender { 
    CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 
    [scale setToValue:[NSNumber numberWithFloat:0.8]]; 
    [scale setAutoreverses:YES]; 
    [scale setDuration:0.3]; 

    //Create animation to adjust the container views anchorpoint. 
    CABasicAnimation *adjustAnchor = [CABasicAnimation animationWithKeyPath:@"anchorPoint"]; 
    [adjustAnchor setFromValue:[NSValue valueWithCGPoint:self.superview.layer.anchorPoint]]; 
    [adjustAnchor setToValue:[NSValue valueWithCGPoint:CGPointMake(self.center.x/self.superview.frame.size.width, self.center.y/self.superview.frame.size.height)]]; 
    [adjustAnchor setRemovedOnCompletion:NO]; 
    [adjustAnchor setFillMode:kCAFillModeForwards]; 

    //Create animation to rotate the container view within its superview. 
    CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 

    //Create the animation group to apply these transforms 
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 
    [animationGroup setAnimations:@[adjustAnchor,rotation]]; 
    [animationGroup setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; 
    [animationGroup setDuration:0.6]; 

    //Apply the end results of the animations directly to the container views layer. 

    [self.superview.layer setTransform:CATransform3DRotate(CATransform3DIdentity, DEGREES_TO_RADIANS(-self.rotationInSuperview), 0.0f, 0.0f, 1.0f)]; 
    [self.superview.layer setAnchorPoint:CGPointMake(self.center.x/self.superview.frame.size.width, self.center.y/self.superview.frame.size.height)]; 
    [self.superview.layer addAnimation:animationGroup forKey:@"animationGroup"]; 

    //Animate the alpha property of all ImpressLabels in the container view. 
    [self.superview bringSubviewToFront:self]; 
    [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 
     for (ImpressLabel *label in sender.view.superview.subviews) { 
      if ([label isKindOfClass:[ImpressLabel class]]) { 
       if (label != self) { 
        [label setAlpha:0.25f]; 
       }else{ 
        [label setAlpha:1.0f]; 
       } 

      } 
     } 
    } completion:nil]; 
} 

ここで、あなたの質問に記載されている懸念の一部に対処する。

私はInstrumentsの配分ツールでこのプロジェクトをプロファイリングしまし
  1. 、それ だけで、全体の約3.2 MBが消費したので、私はこのアプローチは 十分に効率的であると思います。

  2. 私が提供したサンプルは、ほとんどの場合錯視であるスケーリングアニメーションを除いて、2D空間でほとんどのオブジェクトをアニメーションします。私がここで行ったことは、これがどのようにできるかの例として役立つことを意図しており、上で述べたように、アニメーションは本当に私の専門分野ではないので、100%完全なデモンストレーションではありません。しかし、ドキュメントを見渡すと、3次元でラベルを回転させ、スーパービューを調整してすべてのラベルを回転し、選択したラベルをフラットにするキーのように思えるのは、CATransform3DInvert()です。私はそれが完全に理解する時間がまだありませんが、このシナリオで必要とされているものが正確かもしれないように見えます。

  3. ミラーリングが行われる限り、私はすべてを適切にスケーリングすることに問題があるとは思わない。 AppleのMultiple Display Programming Guideを見ると、NSNotificationUIScreenDidConnectNotificationに渡されたオブジェクトがUIScreenオブジェクトであるように見えます。これが当てはまるので、この境界の表示を簡単に要求し、それに応じてラベルのフレームとコンテナのビューを調整します。

注:この例では、のみ0、90、180、及び-90度が原因誤って生成されたアンカーポイントの座標に、正確に100%をアニメーションに変換します。解決方法はCGPointApplyAffineTransform(<#CGPoint point#>, <#CGAffineTransform t#>)であるように見えますが、私が好きだったのと同じくらい遊んだ時間はありませんでした。いずれにせよ、これはあなたの再生を始めるのに十分なはずです。

これは間違いなく私の関心を引いてくれました。私はこのことをもう一度やり直すチャンスを得ると、私はこの情報を新しい情報で喜んで更新します。お役に立てれば!

+0

恐ろしい! 「もう一つ、3Dに気付いたことはありますか?」ということは重要ではありません。回転とパニングは最大のものです。回転とパンがあると、パンは最後の2秒でジャークするようです。 2Dスケーリングは素晴らしいでしょう。 Dropboxの代わりにGithubにプロジェクトを置く必要があります。そうすれば、常に答えが得られます。 – Luke

+0

@ルーク残念ながら私はそれを100%できなかった。ジャンプは、直角に回転していないラベルにアニメートするときにのみ発生します。これは、コンテナのアンカーポイントの座標が変換から正しく設定されていないためです。私がCGPointApplyAffineTransform()の答えで述べたように、これを治すように見えますが、私はまだこの作業をすることができません。そして、私はこれをDropboxに残しておき、いくつかのバグを取り除くと、Githubでこれを喜んでホストします。 –

+0

おかげさまでありがとう、本当にありがとうございます! – Luke

1

CALayerにテキストを描画すると役立つと思います。 https://github.com/ZaBlanc/CanvasKit アニメーションの次のステップを新しいCALayerに描画し、それを変換します。私はそれがこの再現を実現するためにクォーツを残す必要だとは思わないhttps://github.com/clayallsopp/Walt

+0

最後のリンクはRubyだ。 CanvasKitは[NSString drawAtPoint]を使用しているようです。メモリ消費量はUILabelよりも低く見えるので、確かにチェックアウトする価値があります、ありがとう! – Luke

関連する問題