Animate CAShapeLayer with wave animation
Asked Answered
H

1

7

Below i have attached image,I want to achieve the below animation.I have tried water wave animation but don't know how to control the animation like the above.

I have CAShapeLayer in which i have to achieve this animation.

enter image description here

Init Code

UIBezierPath *leftPath = [UIBezierPath bezierPath];
// Set the starting point of the shape.
[leftPath moveToPoint:CGPointMake(0,self.bounds.size.height/2)];
// Draw the lines.


[leftPath addLineToPoint:CGPointMake(0,self.bounds.size.height/2)];
[leftPath addLineToPoint:CGPointMake(self.bounds.size.width,self.bounds.size.height/2)];


leftLayer.path = leftPath.CGPath;
leftLayer.strokeColor = [[UIColor whiteColor] CGColor];
leftLayer.fillColor = nil;
leftLayer.borderWidth = 3.0f;
leftLayer.lineCap = kCALineCapRound;
leftLayer.lineJoin = kCALineJoinRound;

leftLayer.borderColor=[UIColor blackColor].CGColor;
[self.layer addSublayer:leftLayer];

Animation Code

-(void)animateCureve{

CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnimation.duration = 3.5;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAnimation.fromValue = (id)leftLayer.path;
pathAnimation.toValue = (id)[self wavePath].CGPath;
pathAnimation.removedOnCompletion=NO;
[leftLayer addAnimation:pathAnimation forKey:@"path"];
}

The Curve Path

- (UIBezierPath *)wavePath {
//set start and end accordingly

UIBezierPath *startPath = [UIBezierPath bezierPath];
[startPath moveToPoint:CGPointMake(0, self.bounds.size.height/2)];
[startPath addCurveToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height/2) controlPoint1:CGPointMake(50, self.bounds.size.height/2+0)  controlPoint2:CGPointMake(self.bounds.size.width/2, 20) ];



return startPath;
}
Hodosh answered 20/7, 2015 at 14:41 Comment(2)
i have eedited .plz check.I gives continuous wave ,with NSTimerHodosh
hey @ZevEisenberg i have edited the code ,can u please checkHodosh
W
2

Taking a closer look at the frames, it looks like a shallow quadratic curve moving along the path. What you could try is define a range for the beginning and ending of the curve, say start and end, and then add the control point in the middle. Then just add the straight lines at both ends afterwards. Something I quickly wrote:

CGFloat start;
CGFloat end;
CGFloat heightOfQuad;
CGFloat mid = (start + end)/2;

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(start, 0)];
[path addQuadCurveToPoint:CGPointMake(end, 0) controlPoint:CGPointMake(mid, heightOfQuad)];

UIBezierPath *startPath = [UIBezierPath bezierPath];
[startPath moveToPoint:CGPointMake(0, 0)];
[startPath addLineToPoint:CGPointMake(start, 0)];

UIBezierPath *endPath = [UIBezierPath bezierPath];
[endPath moveToPoint:CGPointMake(end, 0)];
[endPath addLineToPoint:CGPointMake(lengthOfViewHere, 0)];

[startPath appendPath:path];
[startPath appendPath:endPath];

*I haven't tested this out yet, but you can give it a go

UPDATE:

- (UIBezierPath *)wavePath {

    CGFloat mid = (self.start + self.end)/2;
    CGFloat y = self.frame.size.height;

    UIBezierPath *curvePath = [UIBezierPath bezierPath];
    [curvePath moveToPoint:CGPointMake(self.start, y)];
    [curvePath addQuadCurveToPoint:CGPointMake(self.end, y) controlPoint:CGPointMake(mid, y - waveHeight)];

    UIBezierPath *startPath = [UIBezierPath bezierPath];
    [startPath moveToPoint:CGPointMake(0, y)];
    [startPath addLineToPoint:CGPointMake(self.start, y)];

    UIBezierPath *endPath = [UIBezierPath bezierPath];
    [endPath moveToPoint:CGPointMake(self.end, y)];
    [endPath addLineToPoint:CGPointMake(self.frame.size.width, y)];

    [startPath appendPath:curvePath];
    [startPath appendPath:endPath];

    return startPath;
}
- (void)setWavePosition:(CGFloat)wavePosition {

    //from 0.0 to 1.0
    _wavePosition = wavePosition;

    //set start and end accordingly
    CGFloat waveCoordinate = wavePosition * self.frame.size.width;
    self.start = waveCoordinate - waveWidth/2;
    self.end = waveCoordinate + waveWidth/2;

    self.path = [self wavePath].CGPath;
    [self setNeedsDisplay];
}

After playing around some, the code above generates this with position at 0.5, waveHeight at 5.0, and waveWidth of 150.0 in a view width of 200.0: enter image description here

All you should need to do is set wavePosition, and then wavePath will give back the new path.

Wilow answered 20/7, 2015 at 15:2 Comment(6)
Could you tell us what's happening? Where did you put this code?Wilow
i cretaed the CAShapeLayer and used CABasicAnimation to animate from and to value path property.I from it was straight path and in topath i used ur pathHodosh
I wrote this thinking you had subclassed CAShapeLayer. I was thinking something of more like you had a property keeping track of the wave, and you would set that in the animation property.Wilow
Oh, wow, dumb mistake on my part, I've updated the answer. I'm also testing something out on my end, I'll post another update soonWilow
Thnks @DavidCao, i will also try at ma endHodosh
The curve u made is perfect ,but when u animate it doesn't work as shown in image.I have posted the codeHodosh

© 2022 - 2024 — McMap. All rights reserved.