iOS贝塞尔曲线月牙型裁剪

摘要

本文旨在记录使用贝塞尔曲线实现一个小需求的完整过程。使用贝塞尔曲线绘制遮罩图层实现如下图头像叠放效果。

关键字

Objective-C 贝塞尔曲线 反余弦

头像堆叠效果示例

说明

项目中已有代码使用 UICollectionView 来实现横向的排列。每个头像都是一个单独的 Cell,每个 Cell 上都有一个自定义的 UIImageView,无需设置圆角裁成圆形。如果按照从左往右的顺序叠放,正常情况下右边的会遮挡左边的头像,这与想要的效果相悖,所以采用给右边的头像裁剪出月牙的形式来模拟被遮挡的效果。

细节

两个头像堆叠时,可以看成是两个等圆相交。在已知两个圆心距离的情况下,求出两个交点所对应圆心角的弧度,根据弧度给需要月牙形绘制Mask遮罩。

  • 下图是两个半径为 15 的圆相交,那么短弧 ADC 和长弧 ABC 所组成的区域就是我们所需要的区域。


    等圆相交.png
  • 根据余弦定理及反余弦函数求出交点 A 和 C 组成的圆心角弧度

    此处 c 为两个圆心的距离,ba 因为等圆所以相等
    CGFloat angle = 2 * acos((c * c)/(2 * a * c));
  • 有了圆心角的弧度,还要再确定一长一短两个弧线的起始和结束位置(两个交点)在下图中位置


    radians_circle.jpeg

长弧 ABC :在 π 值上下分别加减angle的一半

CGFloat startAngle1 =  M_PI + (angle/M_PI/2) * M_PI;
CGFloat endAngle1   =  M_PI - (angle/M_PI/2) * M_PI; 

先调用UIBezierPathbezierPathWithArcCenter:方法绘制长弧 ABC。 其中 center1 为圆心的 Pointclockwise采用顺时针方向。

UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center1 radius:radius startAngle:startAngle1 endAngle:endAngle1 clockwise:YES];
  • 类似的,我们求出绘制短弧 ADC 所需要的参数
    短弧 ADC在 (0,2π) 附近,另外还需注意,为了两段弧线可以正确组成想要的月牙形状。短弧的起始位置需要从长弧的结束位置开始。所以和绘制长弧略有不同。
 CGFloat startAngle2 = (angle/M_PI/2) * M_PI;
 CGFloat endAngle2   = M_PI * 2 - (angle/M_PI/2) * M_PI;

调用UIBezierPathbezierPathWithArcCenter:方法绘制短弧 ADC(CDA)。 其中 center2 为 短弧圆心的 Pointx 轴方向距离长弧圆心距离为 cclockwise采用逆时针方向。

UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center2 radius:radius startAngle:startAngle2 endAngle:endAngle2 clockwise:NO];

这样一来,以长弧的结束点位置为起点绘制出短弧。两个圆弧恰好可以衔接。只需调用如下方法即可

[path1 appendPath:path2];

最后使用CAShapeLayer

 CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = path1.CGPath;
layer.strokeColor = [UIColor clearColor].CGColor;
self.imageView.layer.mask = layer;

设置完 mask 就能让两段圆弧组成的区域显示出月牙形的头像了。

本文开头提到头像列表采用的 UICollectionView 实现横向排列,还需要设置水平间距。其中 radius 为半径, c 为两个圆心的距离

flowLayout.minimumLineSpacing = 2 * radius - c;

你可能感兴趣的:(iOS贝塞尔曲线月牙型裁剪)