Обтравочные тени, созданные CALayer.shadow - PullRequest
9 голосов
/ 19 марта 2012

Я хочу добавить тень по ВНЕШНЕМУ краю HOLLOW CGPath (эти два слова имеют решающее значение: outside + hollow :)).

Реализация теней Apple позволяет только создавать «заполненные» тени.

Итак ... как обрезать внутреннюю часть самой тени?Если бы это был вызов рендеринга, я бы вызвал методы CGContextSetClip *, чтобы обрезать его там, где я хотел ... но я не могу понять, как вы это сделаете, так как это ни вызов рендеринга, ни сам CALayer..

(печальное следствие того, что Apple «скрывает» его как набор магических переменных, я полагаю?)

NB: это только iOS - IIRC на Mac у вас есть прямой доступ кфильтры, используемые для создания теней, так что вы можете создавать свои собственные (произвольные) тени вручную.


ОБНОВЛЕНИЕ:

Я разработал, как обрезать, чтобы показать только ВНУТРЕННЮЮ частьshadow: установите «layer.mask», чтобы быть новым слоем, который является клоном текущего слоя (то есть того же пути), и установите цвет заливки пути на что-либо с полной альфа.

Это противоположночто я пытаюсь, так что если бы я мог найти способ заставить слой маски перевернуть альфа (0 становится 1, 1 становится 0), я был бы там ...

1 Ответ

5 голосов
/ 19 марта 2012

Предположим, у вас есть метод:

-(CAShapeLayer*) cloneShapeLayer; // creates a new CAShapeLayer and copies the values

... затем сделайте это:

  1. Скопируйте слой, создав «маску»
  2. Взять маску- тот же CGPath, запомните - и замените его путь на путь, который имеет:
    1. Прямоугольник всего слоя
    2. МИНУС исходного пути
    3. (достигается с помощью EOправило)
  3. установить маску исходного слоя (с тенью) в качестве нового слоя "mask"

т.е. в коде:

CAShapeLayer* maskLayer = [originalLayer cloneShapeLayer];
// got to make it a bit bigger if your original path reaches to the edge
// since the shadow needs to stretch "outside" the frame:
CGFloat shadowBorder = 50.0;
maskLayer.frame = CGRectInset( maskLayer.frame, - shadowBorder, - shadowBorder );
    maskLayer.frame = CGRectOffset( maskLayer.frame, shadowBorder/2.0, shadowBorder/2.0 );
maskLayer.fillColor = [UIColor blackColor].CGColor;
maskLayer.lineWidth = 0.0;
maskLayer.fillRule = kCAFillRuleEvenOdd;

CGMutablePathRef pathMasking = CGPathCreateMutable();
CGPathAddPath(pathMasking, NULL, [UIBezierPath bezierPathWithRect:maskLayer.frame].CGPath);
CGAffineTransform catShiftBorder = CGAffineTransformMakeTranslation( shadowBorder/2.0, shadowBorder/2.0);
CGPathAddPath(pathMasking, NULL, CGPathCreateCopyByTransformingPath(maskLayer.path, &catShiftBorder ) );
maskLayer.path = pathMasking;

shapeLayer.mask = maskLayer;

Примечание: это действительно работает, за исключением того, что тень, кажется, немного увеличена по сравнению с тем, когда я не маскировал.Ну хорошо.

...