Domanda

I would like to stroke the path of a CAShapeLayer with two alternating colours (black and white for example, think Preview.app selection boxes). I am not sure how to do this, or whether this is even possible with Quartz.

I have set up a CAShapeLayer to have a white border, and then set the path property to be a dashed black line. My hope was that this should give the effect of a black and white dashed lines. However, it seems that the path is drawn first the border is stroked on top, see screenshot (the fur belongs to my cat),

CAShapeLayer with white border and black stroked path, the path is drawn first followed yb the border.

Can anybody suggest a better approach or a way to get this to work?

The code,

// Stroke a white border
[shapeLayer setFrame:shapeRect];
[shapeLayer setBorderColor:[[NSColor whiteColor] CGColor]];
[shapeLayer setBorderWidth:1.0];

// Stroked a black dash path (along the border)
// and fill shape with clear colour
[shapeLayer setFillColor:[[NSColor clearColor] CGColor]];
[shapeLayer setStrokeColor:[[NSColor blackColor] CGColor]];
[shapeLayer setLineWidth:1.0];
[shapeLayer setLineJoin:kCALineJoinRound];
[shapeLayer setLineDashPattern:
 [NSArray arrayWithObjects:[NSNumber numberWithInt:5],
  [NSNumber numberWithInt:5],
  nil]];

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, shapeLayer.bounds);
[shapeLayer setPath:path];
CGPathRelease(path);
È stato utile?

Soluzione

I think there are two problems with that approach (mixing layer border and shape stroke)

  1. The border is on the inside (of the bounds) but the stroke is made from the center (of the path).
  2. The border is drawn after the path is stoked

You can do something about #1 by inseting the path half of the strokeWidth

CGFloat halfWidth = 1.0/2.0;
CGPathAddRect(path, NULL, CGRectInset(shapeLayer.bounds, halfWidth, halfWidth));

However the border is still going to be drawn above the shape (at least I don't know how change the order).

I think the easiest solution is to have to shape layers in the same container layer. The container would be used to change the frame and the two layers would be used to the drawing.

The bottom layer would have a white stroke (no dash pattern) and the top layer would have a dashed black stroke. Since both shapes would have the same path it would look like a black and white dash pattern.

Doing it this way would also work with any shape.

Altri suggerimenti

Did you try to use lineDashPhase property? Using it, you can first display dashed line with black, later - with changed color and lineDashPhase - with white color, over the same path.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top