1

I'm trying to recreate this effect (see image below), but with a circular path as I have a round button.

Here's the source.

https://github.com/uiue/ParticleButton/blob/master/ParticleButton/EmitterView.m

The modifications I've made seem to affect the method that the particle is animated, not the path.

I haven't researched the technology employed in depth, however I don't believe it's possible?

    fireEmitter = (CAEmitterLayer *)self.layer;
    //fireEmitter.renderMode = kCAEmitterLayerAdditive;
    //fireEmitter.emitterShape = kCAEmitterLayerLine;

   // CGPoint pt = [[touches anyObject] locationInView:self];
    float multiplier = 0.25f;
    fireEmitter.emitterPosition = self.center;
    fireEmitter.emitterMode = kCAEmitterLayerOutline;
    fireEmitter.emitterShape = kCAEmitterLayerCircle;
    fireEmitter.renderMode = kCAEmitterLayerAdditive;
    fireEmitter.emitterSize = CGSizeMake(100 * multiplier, 0);

enter image description here

HpTerm
  • 8,151
  • 12
  • 51
  • 67
Jules
  • 7,568
  • 14
  • 102
  • 186

2 Answers2

7

enter image description here

CustomButton.m

-(void)drawRect:(CGRect)rect
{
    //绘制路径
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 3;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:@"easeInEaseOut"];
    animation.repeatCount = MAXFLOAT;
//    animation.path = path;
    animation.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath;
    [emitterView.layer addAnimation:animation forKey:@"test"];
}

Create a custom button in circle shape.

CustomButton *button = [[CustomButton alloc] initWithFrame:CGRectMake(100, 100, 300, 300)];
[self.view addSubview:button];
button.center = self.view.center;
button.layer.cornerRadius = button.frame.size.width/2.f;
button.clipsToBounds = YES;
Hemang
  • 26,840
  • 19
  • 119
  • 186
  • If you want this to look a lot better, change `position` to `emitterPosition` in animationWithKeyPath. – Joe Sep 20 '14 at 13:03
3

You 're just setting the emitter properties there (irrelevant with the animation of its position). The part where the animation is created and added to the button is missing from your question (but is present in the sample project).

There in the drawRect: method the animation is added as follows:

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();

    CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 3;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:@"easeInEaseOut"];
    animation.repeatCount = MAXFLOAT;
    animation.path = path; // That's what defines the path of the animation
    [emitterView.layer addAnimation:animation forKey:@"test"];
}

Which essentially says, take this path (right now a rectangle with the dimensions of the button) and animate the emitterViews (the particles) position along this path for 3 seconds (and repeat forever).

So, a simple change in animation.path to something like this for example could define a circular path for emitter to follow:

animation.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath;

(Essentially an oval with the dimensions of the button - which might be what you want, or not - but you get the idea...)

Note: I'm not suggesting that drawRect: is the best place to create and add the animation (it's just based on the sample that you have provided). You could create and add the animation any way you like provided that you have a path matching your button's circular shape.

Alladinian
  • 34,483
  • 6
  • 89
  • 91
  • Ahhh oh course, I don't know how I missed that, thanks for the full explanation. :) It won't let me award the bounty atm. – Jules Jun 13 '14 at 12:22