1

CALayer の境界をアニメーション化しようとしていますが、うまくいきません。コードは次のとおりです。

class CircleView < UIIVew

  def initWithFrame(frame)
    super

    # determine the dimensions
    radius = (bounds.size.width < bounds.size.height ? bounds.size.width : bounds.size.height) / 2

    # create the circle layer
    @circle = CAShapeLayer.layer
    @circle.bounds = bounds
    @circle.path = UIBezierPath.bezierPathWithRoundedRect(bounds, cornerRadius: radius).CGPath

    @circle.fillColor = UIColor.blueColor.CGColor

    # add the circle to the view
    self.layer.addSublayer(@circle)

    shrink

    self
  end

  private

  # Applies the shrink animation to the provided circle layer.
  def shrink

    # determine the bounds
    old_bounds = @circle.bounds
    new_bounds = CGRectMake(old_bounds.size.width / 2, old_bounds.size.height / 2, 0, 0)

    # animate the shrinking
    animation = CABasicAnimation.animationWithKeyPath("bounds")
    animation.fromValue = NSValue.valueWithCGRect(old_bounds)
    animation.toValue = NSValue.valueWithCGRect(new_bounds)
    animation.duration = 3.0
    @circle.addAnimation(animation, forKey:"bounds")

    # set the bounds so the animation doesn't bounce back when it's complete
    @circle.bounds = new_bounds
  end

  # Applies the shrink animation to the provided circle layer.
  def disappear

    # animate the shirnk
    animation = CABasicAnimation.animationWithKeyPath("opacity")
    animation.fromValue = NSNumber.numberWithFloat(1.0)
    animation.toValue = NSNumber.numberWithFloat(0.0)
    animation.duration = 3.0
    @circle.addAnimation(animation, forKey:"opacity")

    # set the value so the animation doesn't bound back when it's completed
    @circle.opacity = 0.0
  end
end

メソッドから消えるinitWithFrameと、アニメーションは正常に動作します。ただし、shrink を呼び出しても何も起こりません。私は何を間違っていますか?

4

2 に答える 2

6

を使用しているためですCAShapeLayer。はpathとは独立してboundsいるため、個別にアニメートする必要があります。

Objective C に大まかに翻訳されたバージョンのコードで問題を再現できました。shrinkメソッドをこれに変更すると、次のように機能しました。

-(void)shrink
{
  CGRect old_bounds = self.circle.bounds;
  CGRect new_bounds = CGRectMake(old_bounds.size.width / 2, old_bounds.size.height / 2, 0, 0);

  // bounds
  CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"bounds"];
  animation.fromValue = [NSValue valueWithCGRect: old_bounds];
  animation.toValue = [NSValue valueWithCGRect: new_bounds];
  animation.duration = 3.0;
  [self.circle addAnimation: animation forKey: @"bounds"];

  // path
  CGPathRef old_path = self.circle.path;
  CGPathRef new_path = [UIBezierPath bezierPathWithRoundedRect:new_bounds cornerRadius:0].CGPath;

  CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath: @"path"];
  pathAnimation.fromValue = (__bridge id)(old_path);
  pathAnimation.toValue = (__bridge id)(new_path);
  pathAnimation.duration = 3.0;
  [self.circle addAnimation: pathAnimation forKey: @"path"];

  //set the value so the animation doesn't bound back when it's completed
  self.circle.bounds = new_bounds;
  self.circle.path = new_path;
}

技術的には、境界をアニメートする必要さえないかもしれません。レイヤーに個別の値を設定するとbackgroundColorcircle少し実験して、どのように設定し、多かれ少なかれ独立してアニメーション化できるかboundsを簡単に確認できます (たとえば、元のコードでは、境界が実際にアニメーション化されているのにパスがpathそのままです)。

于 2013-08-03T09:27:17.980 に答える