I'm trying to create a sort of progress bar class that fills along a UIBezierPath as it progresses. I need to stroke a UIBezierPath with a controlled animation.
I think I could implement this if I could truncate the path to a precise portion of its original length. Is this possible? Is there another method I can use to precisely control the animated stroking of a path?
I've seen this question, but the answer seems to address finding the points at the beginning and end of each element. I'd need to get a list of points at a pixel-by-pixel level for a list of points to be a viable solution.
I believe I'm looking for the strokeEnd property.
Related
Say you have a UIBez you have built:
Now I want to "clip" it, perhaps with this rectangle:
So in the example the final path I want would be:
(Alternately in the example you could "subtract" a rectangle on the right and one on the bottom.)
Does the iOS toolkit include this ability for UIBezierPath construction?
I think the answer is "No" but it's one of those things that is impossible to google, because, you get unrelated QA. So I cannot find the answer.
Pls note - this is totally different from simply "adding a hole" as one does as a commonplace using .append (example of that https://stackoverflow.com/a/57514286/294884 )
There is no built-in clipping of paths (and definitely no auto-closing of clipped paths, either).
Beyond the “adding a hole” technique that you’ve mentioned, the other approach is just masking/clipping it. And I know you know this, but for the sake of future readers, the built-in clipping/masking is only available within a graphics context (or the mask of a CALayer). For example, if you have a CAShapeLayer, you can set its mask (to the rect illustrated by the dashed rectangle below, for example):
Obviously, this approach can’t “close” the path(s) that have been clipped.
However, if your paths consist of a series of line segments, you theoretically could write your own routine to iterate through those line segments looking for intersections with your rectangular clipping mask (as well as detecting whether they’re contained by the clipping mask at all). If you search for “UIBezierPath intersection”, you will see some relevant examples. Even then, you’ll have interesting edge cases about how to algorithmically close your paths.
I have stumbled upon an interesting problem and I am not sure how to solve it. I have a line graph on which data points are marked with circular dots. At the moment I am creating one CAShapeLayer for the line itself and also CAShapeLayer for each dot.
The line is being animated with the strokeEnd animation key path. And it is working. However, the slightly negative effect is that once I open the graph I see all the data points already drawn and then a line is being animated through them.
Ideally I would like to change this behaviour in such a way that at the beginning nothing is shown and as the line gets animated data points are being drawn once the line passes through them.
I was thinking about this problem for some time now and I cannot find an elegant way of solving it. It seems to me that there should be a fairly easy way of achieving what I want. Maybe I should create a compounded path (but then how do I specify that a line needs to be stroked whereas dots need to be filled?).
Could anyone please guide me in the right direction?
There are lots of ways to handle this.
Assuming that the X increments of your graph are constant, and you're using linear timing, you could simply divide the total animation time by the number of data-points, and calculate the times when you need to add points to the graph when the line progresses to that X position. Simply add dot shape layers to the parent view's layer at the appropriate time intervals.
You could also change your drawing method to add new line segments to your graph path one at a time, on a timer, and add dot shapes at the same time. That would give you a step-by-step animation rather than a smooth line drawing.
So say I wanted to animate drawing this shape:
Animate it something like the disney logo which seems to "write" the letters.
Ideally, I'd also like to have control over how fast it was drawn (maybe just easing), how would I go about getting that done? Specifically imagine if that link had a line of varying widths.
Not too familiar with drawing things in objective-c so perhaps someone can help point me in the right direction in terms of strategy.
Create a CAShapeLayer and set that shape as its path. Use a CABasicAnimation or a CAKeyframeAnimation to animate its strokeEnd property.
Quick diagrams! I'm trying to implement this:
I have this working almost 100% currently (though this is a slightly different stage of the animation):
Everything looks good minus the fade effects at the end of the stroke. Is that possible using a simple CGPath? I'm animating strokeStart and strokeEnd to get the current effect. I've tried using CAGradientLayer as a mask on the layer, but that adds a gradient over the entire layer, not just the ends. Overriding drawRect isn't possible since I'm doing this dynamically with animations.
Any thoughts about how to achieve this effect? I have no idea which direction to go.
Depending on how important opacity is and how complex the rest of the animation is, one option would be to make two blurred tail objects that follow the ends of the path as it is animating.
Roundabout solution, sorry I can't think of another versatile way!
I want to draw a Circle with Letter punched out of it. to do this, I need to stroke the circle clockwise and the letter counterclockwise.
That is all good and well, but when I get the letter path using Core Text I can't figure out how to essentially reverse the path. NOT MIRROR or ROTATE or anything...that is straightforward enough. I want the point stroke order to be counterclockwise.
it is actually hilariously difficult. I've had entirely too many visual 'off by one' errors.
About all I can think of is to call CGPathApply on the path and save information about all of the points, and then redraw the path in the opposite direction. Remember to call CGPathCloseSubpath when you're done.
iOS 6 introduced -bezierPathByReversingPath
It had some issues at first but it seems to be the answer to this question.