Program Club

iOS Swift에서 원을 어떻게 그리나요?

proclub 2020. 11. 12. 20:31
반응형

iOS Swift에서 원을 어떻게 그리나요?


let block = UIView(frame: CGRectMake(cellWidth-25, cellHeight/2-8, 16, 16))
block.backgroundColor = UIColor(netHex: 0xff3b30)
block.layer.cornerRadius = 9
block.clipsToBounds = true

이것이 제가 지금 가지고있는 것이지만 분명히 그것을하는 올바른 방법은 아닙니다.

가장 간단한 방법은 무엇입니까?


경고! 이것은 잘못된 해결책입니다. 도면층은 그리기 방법에서 무한히 추가됩니다 (보기를 그릴 때마다). 그리기 방법에서 레이어를 추가해서는 안됩니다. 사용 layoutSubview하는 대신

다음과 같이 원을 그릴 수 있습니다.

Swift 2.2 :

    let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100,y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.CGPath

    //change the fill color
    shapeLayer.fillColor = UIColor.clearColor().CGColor
    //you can change the stroke color
    shapeLayer.strokeColor = UIColor.redColor().CGColor
    //you can change the line width
    shapeLayer.lineWidth = 3.0

    view.layer.addSublayer(shapeLayer)

스위프트 3.0 :

    let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle: CGFloat(Double.pi * 2), clockwise: true)

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.cgPath

    //change the fill color
    shapeLayer.fillColor = UIColor.clear.cgColor
    //you can change the stroke color
    shapeLayer.strokeColor = UIColor.red.cgColor
    //you can change the line width
    shapeLayer.lineWidth = 3.0

    view.layer.addSublayer(shapeLayer)

게시 한 코드를 사용하여 뷰에 원을 추가하지 않고 UIView의 모서리를 자릅니다.


다음은 해당 방법을 사용하는 전체 예입니다.

// make the UIView a ring of color
import UIKit
class Ring:UIView
    {
    override func drawRect(rect: CGRect)
        {
        drawRingFittingInsideView()
        }

    internal func drawRingFittingInsideView()->()
        {
        let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2)
        let desiredLineWidth:CGFloat = 1    // your desired value

        let circlePath = UIBezierPath(
            arcCenter: CGPoint(x:halfSize,y:halfSize),
            radius: CGFloat( halfSize - (desiredLineWidth/2) ),
            startAngle: CGFloat(0),
            endAngle:CGFloat(M_PI * 2),
            clockwise: true)

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.CGPath

        shapeLayer.fillColor = UIColor.clearColor().CGColor
        shapeLayer.strokeColor = UIColor.redColor().CGColor
        shapeLayer.lineWidth = desiredLineWidth

        layer.addSublayer(shapeLayer)
        }
    }

여기에 이미지 설명 입력


그러나 엄청나게 편리한 전화가 있습니다.

let circlePath = UIBezierPath (ovalInRect : rect)

경로를 만드는 모든 작업을 수행합니다. (선 두께에 대해 삽입하는 것을 잊지 마십시오 CGRectInset.를 사용하면 매우 쉽습니다 .)

internal func drawRingFittingInsideView(rect: CGRect)->()
    {
    let desiredLineWidth:CGFloat = 4    // your desired value
    let hw:CGFloat = desiredLineWidth/2

    let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) )

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.CGPath
    shapeLayer.fillColor = UIColor.clearColor().CGColor
    shapeLayer.strokeColor = UIColor.redColor().CGColor
    shapeLayer.lineWidth = desiredLineWidth
    layer.addSublayer(shapeLayer)
    }

여기에 이미지 설명 입력


요즘 Swift에서는 실제로

@IBDesignable

@IBInspectable

이런 식 으로 스토리 보드에서 실제로 렌더링을보고 변경할 수 있습니다 !

보시다시피 Storyboard의 Inspector에 실제로 새로운 기능을 추가하며 Storyboard에서 변경할 수 있습니다.

여기에 이미지 설명 입력

다음은 코드입니다 ...

// Dot with border, which you can control completely in Storyboard
import UIKit
@IBDesignable
class Dot:UIView
    {
    @IBInspectable var mainColor: UIColor = UIColor.blueColor()
        {
        didSet { print("mainColor was set here") }
        }
    @IBInspectable var ringColor: UIColor = UIColor.orangeColor()
        {
        didSet { print("bColor was set here") }
        }
    @IBInspectable var ringThickness: CGFloat = 4
        {
        didSet { print("ringThickness was set here") }
        }

    @IBInspectable var isSelected: Bool = true

    override func drawRect(rect: CGRect)
        {
        let dotPath = UIBezierPath(ovalInRect:rect)
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = dotPath.CGPath
        shapeLayer.fillColor = mainColor.CGColor
        layer.addSublayer(shapeLayer)

        if (isSelected) { drawRingFittingInsideView(rect) }
        }

    internal func drawRingFittingInsideView(rect: CGRect)->()
        {
        let hw:CGFloat = ringThickness/2
        let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) )

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.CGPath
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        shapeLayer.strokeColor = ringColor.CGColor
        shapeLayer.lineWidth = ringThickness
        layer.addSublayer(shapeLayer)
        }
    }

마지막으로 UIView (정사각형이고 Storyboard에서 빨간색으로 설정)가 있고이를 빨간색 원으로 바꾸려면 다음을 수행하면됩니다.

// It makes a UIView into a circular dot of color
import UIKit
class Dot:UIView
    {
    override func layoutSubviews()
        { layer.cornerRadius = bounds.size.width/2; }
    }

UIView를 사용하여 그리려면 높이 또는 너비의 반경 /을 만들어야합니다.

그래서 그냥 변경 :

block.layer.cornerRadius = 9

에:

block.layer.cornerRadius = block.frame.width / 2

그러나 높이와 너비를 동일하게 만들어야합니다. coregraphics를 사용하고 싶다면 다음과 같이 할 수 있습니다.

CGContextRef ctx= UIGraphicsGetCurrentContext();
CGRect bounds = [self bounds];

CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0;
CGContextSaveGState(ctx);

CGContextSetLineWidth(ctx,5);
CGContextSetRGBStrokeColor(ctx,0.8,0.8,0.8,1.0);
CGContextAddArc(ctx,locationOfTouch.x,locationOfTouch.y,30,0.0,M_PI*2,YES);
CGContextStrokePath(ctx);

클래스 UIView를 만들고 간단한 원에이 코드를 할당합니다.

import UIKit
@IBDesignable
class DRAW: UIView {

    override func draw(_ rect: CGRect) {

        var path = UIBezierPath()
        path = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100))
        UIColor.yellow.setStroke()
        UIColor.red.setFill()
        path.lineWidth = 5
        path.stroke()
        path.fill()


    }


}

Xcode 8.2.2, Swift 3.x에 대한 @Dario의 코드 접근 방식 업데이트. 스토리 보드에서 정사각형 UIView에서 검은 색 배경을 피하려면 배경색을 "지우기"로 설정합니다.

import UIKit
@IBDesignable
class Dot:UIView
{
    @IBInspectable var mainColor: UIColor = UIColor.clear
        {
        didSet { print("mainColor was set here") }
    }
    @IBInspectable var ringColor: UIColor = UIColor.clear
        {
        didSet { print("bColor was set here") }
    }
    @IBInspectable var ringThickness: CGFloat = 4
        {
        didSet { print("ringThickness was set here") }
    }


    @IBInspectable var isSelected: Bool = true

    override func draw(_ rect: CGRect)
    {

        let dotPath = UIBezierPath(ovalIn: rect)
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = dotPath.cgPath
        shapeLayer.fillColor = mainColor.cgColor
        layer.addSublayer(shapeLayer)

        if (isSelected) { drawRingFittingInsideView(rect: rect) }
    }

    internal func drawRingFittingInsideView(rect: CGRect)->()
    {
        let hw:CGFloat = ringThickness/2
        let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw,dy: hw) )

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = ringColor.cgColor
        shapeLayer.lineWidth = ringThickness
        layer.addSublayer(shapeLayer)
    }
}

시작 각도와 끝 각도를 제어하려면 :

import UIKit
@IBDesignable
class Dot:UIView
{
    @IBInspectable var mainColor: UIColor = UIColor.clear
        {
        didSet { print("mainColor was set here") }
    }
    @IBInspectable var ringColor: UIColor = UIColor.clear
        {
        didSet { print("bColor was set here") }
    }
    @IBInspectable var ringThickness: CGFloat = 4
        {
        didSet { print("ringThickness was set here") }
    }


    @IBInspectable var isSelected: Bool = true

    override func draw(_ rect: CGRect)
    {

        let dotPath = UIBezierPath(ovalIn: rect)
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = dotPath.cgPath
        shapeLayer.fillColor = mainColor.cgColor
        layer.addSublayer(shapeLayer)

        if (isSelected) { drawRingFittingInsideView(rect: rect) }
    }

    internal func drawRingFittingInsideView(rect: CGRect)->()
    {
        let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2)
        let desiredLineWidth:CGFloat = ringThickness   // your desired value

        let circlePath = UIBezierPath(
            arcCenter: CGPoint(x: halfSize, y: halfSize),
            radius: CGFloat( halfSize - (desiredLineWidth/2) ),
            startAngle: CGFloat(0),
            endAngle:CGFloat(Double.pi),
            clockwise: true)

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = ringColor.cgColor
        shapeLayer.lineWidth = ringThickness
        layer.addSublayer(shapeLayer)
    }
}

수락 된 답변의 Swift 4 버전 :

@IBDesignable
class CircledDotView: UIView {

    @IBInspectable var mainColor: UIColor = .white {
        didSet { print("mainColor was set here") }
    }
    @IBInspectable var ringColor: UIColor = .black {
        didSet { print("bColor was set here") }
    }
    @IBInspectable var ringThickness: CGFloat = 4 {
        didSet { print("ringThickness was set here") }
    }

    @IBInspectable var isSelected: Bool = true

    override func draw(_ rect: CGRect) {
        let dotPath = UIBezierPath(ovalIn: rect)
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = dotPath.cgPath
        shapeLayer.fillColor = mainColor.cgColor
        layer.addSublayer(shapeLayer)

        if (isSelected) {
            drawRingFittingInsideView(rect: rect)
        }
    }

    internal func drawRingFittingInsideView(rect: CGRect) {
        let hw: CGFloat = ringThickness / 2
        let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw, dy: hw))

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = ringColor.cgColor
        shapeLayer.lineWidth = ringThickness
        layer.addSublayer(shapeLayer)
    }
}

Core Graphics는 Swift 3의 경우 매우 간단합니다 .

if let cgcontext = UIGraphicsGetCurrentContext() {
    cgcontext.strokeEllipse(in: CGRect(x: center.x-diameter/2, y: center.y-diameter/2, width: diameter, height: diameter))
}

보기에 추가가로드되었습니다.

    //Circle Points

     var CircleLayer   = CAShapeLayer() 

    let center = CGPoint (x: myCircleView.frame.size.width / 2, y: myCircleView.frame.size.height / 2)
    let circleRadius = myCircleView.frame.size.width / 2
    let circlePath = UIBezierPath(arcCenter: center, radius: circleRadius, startAngle: CGFloat(M_PI), endAngle: CGFloat(M_PI * 4), clockwise: true)
    CircleLayer.path = circlePath.cgPath
   CircleLayer.strokeColor = UIColor.red.cgColor
    CircleLayer.fillColor = UIColor.blue.cgColor
    CircleLayer.lineWidth = 8
    CircleLayer.strokeStart = 0
    CircleLayer.strokeEnd  = 1
    Self.View.layer.addSublayer(CircleLayer)

승수 백분율을 사용하여 창틀 중앙에 원을 그리는 간단한 기능

/// CGFloat is a multiplicator from self.view.frame.width
func drawCircle(withMultiplicator coefficient: CGFloat) {

    let radius = self.view.frame.width / 2 * coefficient

    let circlePath = UIBezierPath(arcCenter: self.view.center, radius: radius, startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.cgPath

    //change the fill color
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = UIColor.darkGray.cgColor
    shapeLayer.lineWidth = 2.0

    view.layer.addSublayer(shapeLayer)
}

참고 URL : https://stackoverflow.com/questions/29616992/how-do-i-draw-a-circle-in-ios-swift

반응형