Gradient fade at the end of a truncate word - ios

I'm trying to get to a result like this:
And I can't seem to the get there, this is the code I have:
if (size.width > self.name.bounds.size.width) {
CAGradientLayer *l = [CAGradientLayer layer];
CGRect myFrame = self.name.bounds;
myFrame.size.width = 10.0f;
l.frame = myFrame;
l.colors = #[(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor];
l.startPoint = CGPointMake(0.0f, 0.0f);
l.endPoint = CGPointMake(1.0f, 0.0f);
self.name.layer.mask = l;
}
What I'm currently getting is this:
Any help?

The issue with your code is that you are fixing the layer size here.
myFrame.size.width = 10.0f;
The above line fixes the frame size to 10 pixel. So that the layer size will be going to 10 pixel. And the layer can only render on this width.
Just comment or remove above line to get the desired result.
So that your code will be now like
CAGradientLayer *l = [CAGradientLayer layer];
CGRect myFrame = self.name.bounds;
// myFrame.size.width = 10.0f;
l.frame = myFrame;
l.colors = #[(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor];
l.startPoint = CGPointMake(0.0f, 0.0f);
l.endPoint = CGPointMake(1.0f, 0.0f);
self.name.layer.mask = l;
For the bonus - You can make this effect more smooth by adding more colours into the array and by changing the startPoint and endPoint of the layer.
CAGradientLayer *l = [CAGradientLayer layer];
CGRect myFrame = self.name.bounds;
l.frame = myFrame;
l.colors = #[(id)[UIColor lightGrayColor].CGColor, (id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor];
l.startPoint = CGPointMake(0.0, 0.5);
l.endPoint = CGPointMake(1.0, 0.5);
self.name.layer.mask = l;

Related

How to add square gradient border on view - ios

I want to apply square gradient border on view like top window in image:
What i have done:
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
gradientLayer.frame = CGRectMake(0, 0, _imgView.bounds.size.width, _imgView.bounds.size.height);
gradientLayer.startPoint = CGPointMake(0.0, 0.5);
gradientLayer.endPoint = CGPointMake(1.0, 0.5);
gradientLayer.colors = #[(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor];
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.lineWidth = 50;
shapeLayer.path = [UIBezierPath bezierPathWithRect:_imgView.bounds].CGPath;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
gradientLayer.mask = shapeLayer;
[_imgView.layer addSublayer : gradientLayer];
I want gradient border effect as in first image.

Is it possible to apply a vertical gradient as well as a horizontal gradient fade-out on the sides of a graph?

Is it possible to apply a vertical gradient as well as a horizontal gradient fade-out on the sides of a graph?
Here is an image that demonstrates what I am talking about. You can see that the graph in the back has a vertical CPTGradient fill for areaFill.
The code for that would roughly be like this:
CPTGradient *areaGradient = [CPTGradient gradientWithBeginningColor:[[CPTColor whiteColor] colorWithAlphaComponent:.5f] endingColor:[[CPTColor whiteColor] colorWithAlphaComponent:.1f]];
areaGradient.angle = -90.0;
CPTFill *areaGradientFill = [CPTFill fillWithGradient:areaGradient];
tempPlot.areaFill = areaGradientFill;
tempPlot.areaBaseValue = CPTDecimalFromDouble(0.0);
For the edges of the graph, I would do something like this:
CPTGradient *gradient2 = [[CPTGradient alloc] init];
gradient2 = [gradient2 addColorStop:[CPTColor clearColor] atPosition:0.0];
gradient2 = [gradient2 addColorStop:[[CPTColor whiteColor] colorWithAlphaComponent:.5f] atPosition:.05];
gradient2 = [gradient2 addColorStop:[CPTColor clearColor] atPosition:.05];
gradient2 = [gradient2 addColorStop:[CPTColor clearColor] atPosition:1.];
gradient2.angle = 180.f;
tempPlot.areaFill2 = [CPTFill fillWithGradient:gradient2];
tempPlot.areaBaseValue2 = CPTDecimalFromDouble(0.0);
However, the problem is that this doesn't play nicely with the other gradient:
How can I achieve a 'fade out' effect on each side of the plot?
I ended up finding the answer. For the fade on the edges of the graph, I use a CAGradientLayer mask on the host view, where self.hostView is of type CPTGraphHostingView
CAGradientLayer *l = [CAGradientLayer layer];
l.frame = self.hostView.bounds;
l.colors = #[ (id)[UIColor clearColor].CGColor, (id)[UIColor whiteColor].CGColor,
(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor ];
l.locations = #[ #0.f, #0.02f, #0.98f, #1.f ];
l.startPoint = CGPointMake(0.f, 0.5f);
l.endPoint = CGPointMake(1.0f, 0.5f);
self.hostView.layer.mask = l;

Drawing gradient over image in ios

How to create gradient colour look like following image programatically.
When you say "apply it over the image as a gradient", do you mean as a mask (revealing the image at the top, having it fade the image to transparent at the bottom)? If that's the case, you can apply that gradient as a mask, using CAGradientLayer:
CAGradientLayer *gradientMask = [CAGradientLayer layer];
gradientMask.frame = self.imageView.bounds;
gradientMask.colors = #[(id)[UIColor whiteColor].CGColor,
(id)[UIColor clearColor].CGColor];
self.imageView.layer.mask = gradientMask;
The above does a simple vertical gradient (because the default is vertical, linear gradient). But you asked about startPoint, endPoint, and locations. If for example, you wanted your mask applied horizontally, you would do:
gradientMask.startPoint = CGPointMake(0.0, 0.5); // start at left middle
gradientMask.endPoint = CGPointMake(1.0, 0.5); // end at right middle
If you wanted to have two gradients, one at the first 10% and another at the last 10%, you'd do:
gradientMask.colors = #[(id)[UIColor clearColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor clearColor].CGColor];
gradientMask.locations = #[#0.0, #0.10, #0.90, #1.0];
If you want a simple gradient by itself (not as a mask), you'd create a view and then add the gradient layer to it:
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = #[(id)[UIColor whiteColor].CGColor,
(id)[UIColor blackColor].CGColor];
[view.layer addSublayer:gradient];
See the CAGradientLayer class reference.
I just wrote an UIImage extension for Swift 2.0. Maybe it's of some use. You call it with an array of UIColor (any number) and a frame where the gradient should be drawn.
extension UIImage {
class func convertGradientToImage(colors: [UIColor], frame: CGRect) -> UIImage {
// start with a CAGradientLayer
let gradientLayer = CAGradientLayer()
gradientLayer.frame = frame
// add colors as CGCologRef to a new array and calculate the distances
var colorsRef = [CGColor]()
var locations = [NSNumber]()
for i in 0 ... colors.count-1 {
colorsRef.append(colors[i].CGColor as CGColorRef)
locations.append(Float(i)/Float(colors.count-1))
}
gradientLayer.colors = colorsRef
gradientLayer.locations = locations
// now build a UIImage from the gradient
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.renderInContext(UIGraphicsGetCurrentContext()!)
let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// return the gradient image
return gradientImage
}
}
Call it like this:
let colors = [
UIColor.blueColor(),
UIColor.greenColor()
// and many more if you wish
]
let gradientImage = UIImage.convertGradientToImage(colors, frame: navigationBar.bounds)
and apply with:
.backgroundColor = UIColor(patternImage: gradientImage)
or
.setBackgroundImage(gradientImage, forBarMetrics: .Default)
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.view.bounds;
gradient.startPoint = CGPointMake(1.0, 1.0); //Dark From bottom
gradient.endPoint = CGPointMake(1.0, 0);
gradient.colors = [NSArray arrayWithObjects:
(id)[[UIColor blackColor] CGColor],
(id)[[UIColor clearColor] CGColor], nil];
[self.view.layer insertSublayer:gradient atIndex:0];
This is the best approach, working for me as requirement
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = yourImageView.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithWhite:1.0f alpha:1.0f].CGColor,
(id)[UIColor colorWithWhite:0.0f alpha:0.9f].CGColor,
nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
[yourImageView.layer addSublayer:gradientLayer];
-(void) drawGradientinBounds: (CGRect) currentBounds withColors:(NSArray*) colors andPercentages:(NSArray *)percentages andGradientDirectionIsVertical:(BOOL)isGradientDirectionVertical
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = [percentages count];
CGFloat locations[num_locations];
for(int i=0;i<num_locations;i++)
locations[i] = [[percentages objectAtIndex:i] floatValue];
int comps = [colors count]*4;
CGFloat components[comps];
for(int i = [colors count]-1;i>=0;i--)
{
comps--;
UIColor *c = [colors objectAtIndex:i];
const CGFloat *cg = CGColorGetComponents([c CGColor]);
components[comps] = cg[3];
comps--;
components[comps] = cg[2];
comps--;
components[comps] = cg[1];
comps--;
components[comps] = cg[0];
}
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGPoint topCenter;
CGPoint endCenter;
if(isGradientDirectionVertical)
{
topCenter = CGPointMake(CGRectGetMidX(currentBounds), currentBounds.origin.y);
endCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetHeight(currentBounds)+currentBounds.origin.y);
}
else
{
topCenter = CGPointMake( currentBounds.origin.x,CGRectGetMidY(currentBounds));
endCenter = CGPointMake(CGRectGetWidth(currentBounds)+currentBounds.origin.x,CGRectGetMidY(currentBounds));
}
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, endCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
And the input to this method are bounds, colorArray:
[NSArray arrayWithObjects:[UIColor blackColor], [UIColor whiteColor], nil]
percentageArray:
[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil]

CAGradientLayer with CAShapeLayer mask not showing

I have the following code:
- (void)setupLayer {
self.faucetShape = [CAShapeLayer layer];
self.faucetShape.strokeColor = [[UIColor blackColor] CGColor];
self.faucetShape.lineWidth = 2;
self.faucetShape.fillColor = nil;
self.faucetShape.path = [self faucetPath].CGPath; // faucetPath returns a 4 point diamond shaped UIBezierPath*
self.faucet = [CAGradientLayer layer];
self.faucet.mask = self.faucetShape;
self.faucet.colors = #[(id)[UIColor redColor].CGColor, (id)[UIColor redColor].CGColor];
[self.layer addSublayer: self.faucet];
}
But it shows nothing. Not sure what I'm missing (other than my graphic).
(faucet and faucetPath are both properties)
UPDATE
OK, I guess a CAGradientLayer has to have a meaningful frame. I assume a CAShapeLayer's frame isn't as meaningful, since the path can go outside the frame. Adding the following line made it show up:
self.faucet.frame = CGRectMake(0, 0, 64, 64);
So NOW my question is, is there a way to avoid having to do that? I'd just like the frame of the layer to implicitly be that of the containing View/Layer.
You need to set the frame of the layers. The following code will draw a red circle:
- (void)setupLayer
{
CAShapeLayer *faucetShape = [CAShapeLayer layer];
faucetShape.frame = CGRectMake(0, 0, 100, 100);
faucetShape.strokeColor = [[UIColor blackColor] CGColor];
faucetShape.lineWidth = 2;
faucetShape.fillColor = nil;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, CGRectMake(0, 0, 100, 100));
faucetShape.path = path;
CGPathRelease(path);
CAGradientLayer *faucet = [CAGradientLayer layer];
faucet.frame = CGRectMake(10, 10, 100, 100);
faucet.mask = faucetShape;
faucet.colors = #[(id)[UIColor redColor].CGColor, (id)[UIColor redColor].CGColor];
[self.view.layer addSublayer: faucet];
}

CAAnimation to end before it reaches it's destination

I have a CaLayer that is moving with a CAKeyframeAnimation. I want to end the movement of the Layer before it reaches the end, because a random number of Layers are moving towards a single destination from different locations, and when they reach it, it looks like a snowflake.
CGPoint startPoints = [self convertDegreesToPoints:latLonArr];
CGPoint endPoints = [self convertDegreesToPoints:[NSArray arrayWithObjects:#"41.0311",#"21.3403", nil]];
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:startPoints];
[linePath addLineToPoint:endPoints];
//gradient layer for the line
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(0, 0, 150.0, 2.0);
gradient.cornerRadius = 5.0f;
gradient.startPoint = CGPointMake(0.0, 0.5);
gradient.endPoint = CGPointMake(1.0, 0.5);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor clearColor] CGColor],(id)[[colors objectAtIndex:i] CGColor],(id)[[colors objectAtIndex:i] CGColor],(id)[[UIColor clearColor] CGColor], nil];
[scrollViewContent.layer addSublayer:gradient];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
anim.path = [linePath CGPath];
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = 0;
anim.duration = 1;
[gradient addAnimation:anim forKey:#"gradient"];
and here is how it looks:
This question is referral to https://stackoverflow.com/questions/20125910/cagradientlayer-to-blend-in-with-the-end-location-of-the-cakeyframeanimation
I decided to ask again because maybe I was not clear enough in the previous one, or title was to strange for someone who knows how, to look into it.

Resources