What is the CAKeyframeAnimation equivalent of CABasicAnimation's fromValue and toValue - cabasicanimation

The CABasicAnimation properties fromValue and toValue make it easy to animate a path, starting from an arbitrary point in the path and lasting for an arbitrary duration. I haven't found an equivalent way to do the same in CAKeyframeAnimation. Alternatively, how can CABasicAnimation be used to animate a path taken from another layer, considering that CABasicAnimation has no path property? (At the moment I am using UIBezierPath, but I suppose the same answer would apply to CGMutablePathRef.)

Related

Best way to make a trailing pixel?

So in swift, for iOS devices (though cross platform would be cool if I can still code in Xcode) I am trying to do something rather simple.
All I want to do is have little particles moving around on the screen leaving trails. Unfortunately I cant use traditional particle systems because I need to program their movement.
Anyway I was figuring that if I could keep all the pixels in a large array and just changing them as I need to. That way I can set pixels based on the particle, and just fade them away each frame, thus giving the illusion of a trail.
What would be a good way to do this? I have been looking at quarts, core graphics, and opengles however I cant find a single tutorial that tells me how to draw a single pixel... Just ones that tell how to draw lines and other stuff. I just need to be able to draw the screen pixel by pixel (unless you have a better idea)
What framework should I use
How do I draw a single pixel in it given an x,y screen coordinate (or link a tutorial).
Thanks much!
CoreImage with CIImageAccumulator can help you do this. In my FurrySketch project, I do something very similar. In a nutshell:
Begin a UI Graphics Context: UIGraphicsBeginImageContext(view.frame.size)
Use functions such as CGContextAddLineToPoint to draw to the context
Create a CIImage of the drawing: let drawnImage = UIGraphicsGetImageFromCurrentImageContext()
Use a CISourceOverCompositing to composite that new image over the previous one in the accumulator and write the composite image back to the accumulator:
compositeFilter.setValue(CIImage(image: drawnImage),
forKey: kCIInputImageKey)
compositeFilter.setValue(imageAccumulator.image(),
forKey: kCIInputBackgroundImageKey)
imageAccumulator.setImage(compositeFilter.valueForKey(kCIOutputImageKey) as! CIImage)
Display the new composite in the UI: imageView.image = UIImage(CIImage: imageAccumulator.image())
By also adding a blur to that image, you can get your particles to fade out too, as I've done here.

How to edit a bezier path in xcode after view loads

I need to be able to update the three points of my bezier path in xcode after the view has loaded.I would like to update my bezier path by a NSTimer. I am able to draw the initial bezier path, but I can't figure out how to change it after the initial loading! I am making a slingshot, so that's why I need to change my bezier path often. ANY Suggestions?
NSBezierPath is an immutable path. Rather than changing an existing one, you need to create a new one with the updated points.

How do I fade out a rectangle over a given time interval in Cocoa?

I am writing a Cocoa application for OS X, where the user can draw squares on an NSView instance by clicking with the mouse. Currently I am making the squares disappear after 2 seconds, using the performSelector:withObject:afterDelay: method of NSObject, to force a redraw of the view, with no square included.
However, instead of just disappearing, I would like the squares to fade out gradually. I've tried using an NSTimer to periodically force a redraw, with the opacity of the square decreasing to 0 over 2 seconds, but this seems rather inelegant and probably inefficient, especially if I have a lot of squares.
Is there an idiomatic way to do this?
UPDATE: just to clarify, I want each square drawn in the view to have an independent fade starting from the point at which it's drawn, I'm not looking to fade out the entire view.
The solution I've ended up using is to create a CALayer instance for each square, rather than using NSRectFill to draw the squares. The opacity of each CALayer instance can then be independently animated using a CABasicAnimation instance. E.g.
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
[animation setFromValue:[NSNumber numberWithFloat:1.]];
[animation setToValue:[NSNumber numberWithFloat:0.]];
[animation setDuration:2.];
[layer setOpacity:0.];
[layer addAnimation:animation forKey:#"opacity"];
NSAnimationContext is probably what you're looking for.

Constructing CAShapeLayer from a multiple CGpaths

I have a CAShapeLayer that takes his shape from path. This creates a layer object which can be manipulated, like move and rotate.
My problem is that I need the layer object to be composed of multiple paths. For example imagine the United States map; there is the main shape and also the Alaska. Both shapes are not connected, but they are the same entity and I need them to be a single object in a single CAShapeLayer, so that when I move the layer both US and Alaska move together.
UIBezierPath* ahPath = [self mydPath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = ahPath.CGPath;
...
[self.layer addSublayer:shapeLayer];
In the case you describe I would make a CAShapeLayer representing the US and a separate CAShapeLayer representing a state, then add the state layer to the US layer. Moving the US layer would automatically move the state layer with it. The advantage is that you can color the US and states differently.
Also be aware that a CGPath can contain multiple subpaths, so one CGPath can contain the US and Alaska. Check the Overview in CGPath Reference.

polyline with gradient

Is there a way to draw a line along a curved path with a gradient that varies in a direction perpendicular to the direction of the line? I am using the GDI+ framework for my graphics.
The simple answer is no. You can create a GraphicsPath in order to describe what you would like to draw, using AddPoint/AddLine/AddBezier and so forth as needed to describe the complex path of what you want to draw. When you draw the path you can provide a Brush which can be something like LinearGradientBrush or RadialGradientBrush. Neither of those gradient brushes reacts to the actual path being drawn in the sense of changing direction as the drawing occurs. You have to specify the angles etc as constant for the entire gradient area.
One possible method you can use is to set the clip region of the Graphics object to be that of the line only. Then draw a Linear Gradient over the extremes of the line e.g.
GraphicsPath gp = new GraphicsPath();
gp.AddArc(); // etc...
graphics.SetClip( gp );
graphics.FillRectangle( myLinearGradientBrush, gp.GetBounds());
The above code might give you what you are looking for.

Resources