UIBezierPath围绕UIView中心旋转

时间:2017-09-10 10:36:05

标签: ios swift uibezierpath cgaffinetransform

我正在创建一个自定义UIView,我在其中使用UIBezierPath绘制一个宽度较大的圆圈来实现其draw(rect:)方法,在顶部绘制一个正方形(如图所示) ,不要考虑颜色或大小)。然后我尝试创建方形的旋转副本,以匹配“设置”图标(图片2,仅考虑外环)。为了做到这一点,我需要使用CGAffineTransform(rotationAngle:)旋转方块,但问题是这个旋转的中心是框架的原点,而不是圆的中心。如何在视图中的某个点周围创建旋转?

picture 1

picture 2

3 个答案:

答案 0 :(得分:6)

作为@DuncanC的答案(已投票)的演示,这里是使用CGAffineTransform s来绘制齿轮绕圆心旋转的齿轮:

class Gear: UIView {
    var lineWidth: CGFloat = 16
    let boxWidth: CGFloat = 20
    let toothAngle: CGFloat = 45

    override func draw(_ rect: CGRect) {

        let radius = (min(bounds.width, bounds.height) - lineWidth) / 4.0

        var path = UIBezierPath()
        path.lineWidth = lineWidth
        UIColor.white.set()

        // Draw circle
        path.move(to: CGPoint(x: center.x + radius, y: center.y))
        path.addArc(withCenter: CGPoint(x: center.x, y: center.y), radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
        path.stroke()

        // Box for gear tooth
        path = UIBezierPath()
        let point = CGPoint(x: center.x - boxWidth / 2.0, y: center.y - radius)
        path.move(to: point)
        path.addLine(to: CGPoint(x: point.x, y: point.y - boxWidth))
        path.addLine(to: CGPoint(x: point.x + boxWidth, y: point.y - boxWidth))
        path.addLine(to: CGPoint(x: point.x + boxWidth, y: point.y))
        path.close()
        UIColor.red.set()

        // Draw a tooth every toothAngle degrees
        for _ in stride(from: toothAngle, through: 360, by: toothAngle) {
            // Move origin to center of the circle
            path.apply(CGAffineTransform(translationX: -center.x, y: -center.y))

            // Rotate
            path.apply(CGAffineTransform(rotationAngle: toothAngle * .pi / 180))

            // Move origin back to original location
            path.apply(CGAffineTransform(translationX: center.x, y: center.y))

            // Draw the tooth
            path.fill()
        }
    }
}

let view = Gear(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

此处它正在Playground中运行:

Demo of gear running in a Playground

答案 1 :(得分:2)

移动变换的原点, 旋转, 转回来

应用您的转换

答案 2 :(得分:0)

如果您想使用UIViews快速创建n脏版本:

UIView * dialView = [UIView new];
dialView.frame = CGRectMake(0, localY, w, 300);
dialView.backgroundColor = [UIColor whiteColor];
[analyticsView addSubview:dialView];

float lineWidth = 6;
float lineHeight = 20.0f;
int numberOfLines = 36;
for (int n = 0; n < numberOfLines; n++){

    UIView * lineView = [UIView new];
    lineView.frame = CGRectMake((w-lineWidth)/2, (300-lineHeight)/2, lineHeight, lineWidth);
    lineView.backgroundColor = [UIColor redColor];
    [dialView addSubview:lineView];

    lineView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(360/numberOfLines*n));
    lineView.transform = CGAffineTransformTranslate(lineView.transform, (150-lineHeight), 0);

}

给予:

enter image description here

其中w是支架宽度,并且弧度的计算公式为:

#define DEGREES_TO_RADIANS(degrees)((M_PI * degrees)/180)