3

内側の影を描画するために生成されたコードを見ました。copysignで影が作成される部分を除いて、すべてが非常に明確で理解されています。

copysign の機能は理解していますが、以下のコードで実際に使用されている理由と方法について説明します。

0.1 値は、xOffset値にとって重要ではないようです。

  CGContextRef context = UIGraphicsGetCurrentContext();
  
  UIColor *shadow = [UIColor redColor];
  CGSize shadowOffset = CGSizeMake(-2, -0);
  CGFloat shadowBlurRadius = 2;

  UIBezierPath *rectanglePath = [UIBezierPath bezierPathWithRect: CGRectMake(50, 50, 50, 50)];
  [[UIColor grayColor] setFill];
  [rectanglePath fill];
  
  CGRect rectangleBorderRect = CGRectInset([rectanglePath bounds], -shadowBlurRadius, -shadowBlurRadius);
  rectangleBorderRect = CGRectOffset(rectangleBorderRect, -shadowOffset.width, -shadowOffset.height);
  rectangleBorderRect = CGRectInset(CGRectUnion(rectangleBorderRect, [rectanglePath bounds]), -1, -1);
  
  UIBezierPath *rectangleNegativePath = [UIBezierPath bezierPathWithRect: rectangleBorderRect];
  [rectangleNegativePath appendPath: rectanglePath];
  rectangleNegativePath.usesEvenOddFillRule = YES;
  
  CGContextSaveGState(context);
  {
    CGFloat xOffset = shadowOffset.width + round(rectangleBorderRect.size.width);
    CGFloat yOffset = shadowOffset.height;
    CGContextSetShadowWithColor(context,
                                CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)),
                                shadowBlurRadius,
                                shadow.CGColor);

    
    [rectanglePath addClip];
    CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(rectangleBorderRect.size.width), 0);
    [rectangleNegativePath applyTransform: transform];
    [[UIColor grayColor] setFill];
    [rectangleNegativePath fill];
  }
  CGContextRestoreGState(context);
4

1 に答える 1

5

ここのPaintCodeの開発者。

影のオフセットは、常に整数ピクセルに「丸め」られます。残念ながら、Core Graphics にはある種の精度/丸めの問題があります。シャドウ オフセットの特定の値では、何らかの理由で丸めが無効になり、不適切なオフセットが使用されます (たとえば、3 ではなく 2)。

シャドウ オフセットに戦略的に 0.1 を加算または減算することで、常に正しく動作するように強制します。

于 2013-11-02T08:35:21.563 に答える