Как AspectFit UIBezierPath в iOS, используя Objective-C - PullRequest
0 голосов
/ 04 сентября 2018

Я пытаюсь установить AspectFit для пользовательской кнопки на основе UIBezierPath.

Вот мой код в пользовательском классе, который является подклассом из UIButton Class

-(id)initWithCoder:(NSCoder *)coder {
   if (self = [super initWithCoder:coder]) {
    self.contentMode = UIViewContentModeScaleAspectFill;
   }
   return self;
}

-(void)drawRect:(CGRect)rect {

 UIColor* fillColor = [UIColor colorWithRed: 0.451 green: 0.855 blue: 1 alpha: 1];

UIBezierPath* clipPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0.01, 81.6, 40.9)];
[clipPath addClip];

UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(81.21, 13.63)];
[bezierPath addCurveToPoint: CGPointMake(48.11, 40.91) controlPoint1: CGPointMake(84.3, 37.04) controlPoint2: CGPointMake(68.27, 40.91)];
[bezierPath addCurveToPoint: CGPointMake(4.72, 45.04) controlPoint1: CGPointMake(33.83, 40.91) controlPoint2: CGPointMake(3.32, 40.91)];
[bezierPath addCurveToPoint: CGPointMake(20.19, 7.94) controlPoint1: CGPointMake(-1.03, 14.37) controlPoint2: CGPointMake(-1.26, 0.28)];
[bezierPath addCurveToPoint: CGPointMake(81.21, 13.63) controlPoint1: CGPointMake(40.97, 1.57) controlPoint2: CGPointMake(78.62, -6.04)];
[bezierPath closePath];
[fillColor setFill];
[bezierPath fill];
}

В xib я назначил пользовательский класс для объекта UIButton. Я пытался использовать обработчики AspectFit в IB, а также пытался в initWithCoder, кажется, ничего не работает.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Я тщательно оценил ширину и высоту рисунка, и это дало мне 82 х 42 точки. Затем я применил масштабный коэффициент в коде, чтобы рисунок мог соответствовать кнопке, если размер кнопки масштабируется в xib.

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, rect.size.width / 82, rect.size.height/ 42);

Теперь полный код выглядит следующим образом.

- (void)drawRect:(CGRect)rect {

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextScaleCTM(context, rect.size.width / 82, rect.size.height/ 42);

  {

  UIColor* fillColor = [UIColor colorWithRed: 0.451 green: 0.855 blue: 1 alpha: 1];


  UIBezierPath* clipPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0.01, 81.6, 40.9)];
  [clipPath addClip];

  UIBezierPath* bezierPath = [UIBezierPath bezierPath];


  [bezierPath moveToPoint: CGPointMake(81.21, 13.63)];
  [bezierPath addCurveToPoint: CGPointMake(48.11, 40.91) controlPoint1: CGPointMake(84.3, 37.04) controlPoint2: CGPointMake(68.27, 40.91)];
  [bezierPath addCurveToPoint: CGPointMake(0.72, 25.04) controlPoint1: CGPointMake(33.83, 40.91) controlPoint2: CGPointMake(3.32, 40.91)];
  [bezierPath addCurveToPoint: CGPointMake(20.19, 0.94) controlPoint1: CGPointMake(-1.03, 14.37) controlPoint2: CGPointMake(-1.26, 0.28)];
  [bezierPath addCurveToPoint: CGPointMake(81.21, 13.63) controlPoint1: CGPointMake(40.97, 1.57) controlPoint2: CGPointMake(78.62, -6.04)];
  [bezierPath closePath];
  [fillColor setFill];
  [bezierPath fill];

  }

}
0 голосов
/ 04 сентября 2018

Возможно, проще всего применить преобразование aspectFit к BezierPath перед его рисованием или применить то же преобразование к графическому контексту. Примерно так:

- (CGAffineTransform) aspectFitFrom:(CGRect)originalRect to:(CGRect)targetRect
{
    CGFloat xScale = targetRect.size.width / originalRect.size.width;
    CGFloat yScale = targetRect.size.height / originalRect.size.height;
    CGFloat scale = MIN(xScale, yScale);

    CGFloat xShift = CGRectGetMidX(targetRect) - CGRectGetMidX(originalRect) * scale;
    CGFloat yShift = CGRectGetMidY(targetRect) - CGRectGetMidY(originalRect) * scale;
    return CGAffineTransformMake(scale, 0, 0, scale, xShift, yShift);
}

Примените это к ограничивающей рамке пути Безье и границам цели. Затем примените преобразование к bezierPath перед его заполнением следующим образом:

CGRect pathBBox = bezierPath.bounds; // the bounding box of your bezierPath
CGAffineTransform transform = [self aspectFitFrom:pathBBox to:rect];
[bezierPath applyTransform:transform];

Вам нужно подумать, что вы хотите сделать с толщиной линии формы, когда она масштабируется.

...