If I create a CAShapeLayer with just a background color it shows up, but if i set the content to an image, nothing shows.
CAShapeLayer* leftDot = [CAShapeLayer layer];
leftDot.opacity = 1.0;
leftDot.frame = CGRectMake(leftRef.CGPointValue.x, leftRef.CGPointValue.y, 2 * radius, 2 * radius);
leftDot.position = CGPointMake(leftRef.CGPointValue.x + 4, leftRef.CGPointValue.y + 4);
leftDot.cornerRadius = radius;
[leftDot setContents:[UIImage imageNamed: @"glow.png"]];
[self.layer addSublayer: leftDot];
CAShapeLayer doesn't work that way. You would create a normal CALayer with the image as its content and then use the shape layer as the mask of that layer to achieve the effect you are after.
[NOTE: updated to Swift 2.2 and Swift 3]
Quick answer: use CALayer
As explained in CAShapeLayer Class Reference, a CAShapeLayer
is used for drawing shapes using a custom path. Setting an image as its contents
will simply be ignored.
If you just want to show an image in a layer (let's suppose your file is named image.png
), you can use a CALayer
and set its contents
property so that it references the CGImage
representation of your image:
Swift 2.2:
let layer = CALayer()
layer.contents = UIImage(named: "image")?.CGImage
Swift 3:
let layer = CALayer()
layer.contents = UIImage(named: "image")?.cgImage
Longer answer: keep using CAShapeLayer
Since the OP asked specifically about CAShapeLayer
, the question may read like "How can I crop an image into a specific shape using CAShapeLayer
?"
There are two solutions I'd suggest you try:
1) Masking
Create a normal CALayer
and set the image as its contents
. Then create a CAShapeLayer
with the path you like and use it as the first layer's mask
.
Swift 2.2:
let imageLayer = CALayer()
imageLayer.contents = UIImage(named: "image")?.CGImage // Assign your image
imageLayer.frame = ... // Define a frame
let maskPath = UIBezierPath(...) // Create your path
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.CGPath
imageLayer.mask = maskLayer // Set the mask
Swift 3:
let imageLayer = CALayer()
imageLayer.contents = UIImage(named: "image")?.cgImage // Assign your image
imageLayer.frame = ... // Define a frame
let maskPath = UIBezierPath(...) // Create your path
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
imageLayer.mask = maskLayer // Set the mask
Don't forget to set the right frames and paths, and you should be able to achieve the effect you wanted.
2) Fill color
Create a CAShapeLayer
with the path you like, then use your image as its fillColor
.
Swift 2.2:
let path = UIBezierPath(...) // Create your path
let layer = CAShapeLayer()
layer.path = path.CGPath
let image = UIImage(named: "image") // Assign your image
layer.fillColor = UIColor(patternImage: image!).CGColor
Swift 3:
let path = UIBezierPath(...) // Create your path
let layer = CAShapeLayer()
layer.path = path.cgPath
let image = UIImage(named: "image") // Assign your image
layer.fillColor = UIColor(patternImage: image!).cgColor
You may find this approach easier at first, but controlling the way the image fills your shape is not trivial at all.
You can get the image to appear by setting the fillColor
rather than the contents
:
layer.fillColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"image"]].CGColor;
layerName.contents = (id)[[UIImage imageNamed:@"img.PNG"] CGImage];
You have to set the CGImage for the layer
leftDot.fillColor=[UIColor clearColor].CGColor ;
[leftDot setContents:(__bridge id)[UIImage imageNamed: @"glow.png"].CGImage];