programing

iOS Swift에서 원을 그리려면 어떻게 해야 합니까?

bestprogram 2023. 8. 15. 11:18

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

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

그것을 하는 가장 간단한 방법은 무엇입니까?

경고. 이 오래된 대답은 완전히 틀렸습니다.

경고! 잘못된 해결 방법입니다.레이어는 에서 무한히 추가됩니다.drawRect메서드(뷰가 그려질 때마다).에서계 추됩안다니에 는 안 .drawRect방법. 사용layoutSubview대신.

이것으로 원을 그릴 수 있습니다(Swift 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보기에 원을 추가하지 않습니다.


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

/// A special UIView displayed as a ring of color
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)
     }
}

A circle outlined in red and filled with yellow on a yellow background.


참고로, 매우 편리한 전화가 있습니다.

let circlePath = UIBezierPath(ovalInRect: rect)

길을 (굵기에 하는 것을 . (인로두위삽것잊마지오십시는을을업하입해를든드께는▁(라▁incred,▁thickness▁line▁which▁easyibly▁which▁is다▁with오마▁also시십▁thedon▁path경'▁foret▁(▁does▁it▁the▁making▁the▁ins▁all. 이것은 또한 믿을 수 없을 정도로 쉽습니다.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)
}

An ellipses (oval-like) outlined in red and filled with yellow on a yellow background.


요즘 스위프트에서 연습할 때, 당신은 확실히 사용할 것입니다.@IBDesignable그리고.@IBInspectable이것들을 사용하면 실제로 스토리보드에서 렌더링을 보고 변경할 수 있습니다!

보다시피 스토리보드에서 변경할 수 있는 새로운 기능이 스토리보드의 Inspector에 추가됩니다.

Xcode Storyboard Attributes Inspector with custom fields.

/// A dot with a border, which you can control completely in Storyboard
@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합니다) 으로 바꾸고 때, 을 할 수 (이것사은스고이설표빨니다록습서로했정수도수있때다습니다할행그을싶바음원빨을색고꾸로으간리단히순고시으각형보드에하간리토색▁(▁the▁just:▁following,(다니▁do있습수▁is▁squarewhich,▁story▁circle▁in)▁red▁and▁youboard▁can▁and▁to▁you▁in할▁want▁set이수▁red.

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

클래스 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()


    }


}

UI뷰를 사용하여 그림을 그리려면 높이 또는 너비의 반지름/반지름을 만들어야 합니다.

그러니 그냥 바꿔요.

block.layer.cornerRadius = 9

대상:

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

하지만 당신은 높이와 너비를 동일하게 만들어야 합니다.코어 그래픽을 사용하려면 다음과 같은 작업을 수행해야 합니다.

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);

여기 스위프트 5와 코어 그래픽을 사용한 제 버전이 있습니다.

저는 두 개의 원을 그리는 클래스를 만들었습니다. 번째 첫번째원다사작성다니됩여용하음을을 사용하여 .addEllipse()타원을 정사각형으로 만들어 원을 만듭니다.는 기능이 .addCircle() 두번째원다사작성다니됩여용하음을은을 사용하여 .addArc() 중 2피라디안

import UIKit

@IBDesignable
class DrawCircles: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        guard let context = UIGraphicsGetCurrentContext() else {
            print("could not get graphics context")
            return
        }

        context.setLineWidth(2)

        context.setStrokeColor(UIColor.blue.cgColor)

        context.addEllipse(in: CGRect(x: 30, y: 30, width: 50.0, height: 50.0))

        context.strokePath()

        context.setStrokeColor(UIColor.red.cgColor)

        context.beginPath() // this prevents a straight line being drawn from the current point to the arc

        context.addArc(center: CGPoint(x:100, y: 100), radius: 20, startAngle: 0, endAngle: 2.0*CGFloat.pi, clockwise: false)

        context.strokePath()
    }
}

didViewLoad()다음을 추가합니다.

let myView = DrawCircles(frame: CGRect(x: 50, y: 50, width: 300, height: 300))

self.view.addSubview(myView)

작동할 때는 이렇게 보여야 합니다.제 솔루션이 마음에 드셨으면 좋겠습니다!

enter image description here

승인된 답변의 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)
    }
}

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

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)
    }
}

훨씬 쉽고 자원 친화적인 접근법이 될 것입니다.

import UIKit

@IBDesignable
class CircleDrawView: UIView {

    @IBInspectable var borderColor: UIColor = UIColor.red;

    @IBInspectable var borderSize: CGFloat = 4

    override func draw(_ rect: CGRect)
    {
        layer.borderColor = borderColor.cgColor
        layer.borderWidth = borderSize
        layer.cornerRadius = self.frame.height/2
    }

}

와 함께Border Color그리고.Border Size기본값Background원의 모양을 정의할 수 있는 속성입니다.

enter image description here

원을 그리려면 보기의 높이와 너비가 크기가 같아야 합니다.

이 코드는 다음에 대해 작동합니다.Swift >= 4그리고.Xcode >= 9.

Swift 3: 코어 그래픽은 매우 간단합니다.

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

곱셈기 백분율을 사용하여 창틀 중간에 원을 그리는 간단한 함수

/// 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)
}

2022년, 실제로 그림을 그리는 방법의 일반적인 예는 다음과 같습니다.draw순식간에UIView.

제대로 사용하기가 쉽지 않습니다.UIView#draw.

  • 일반적인 초보자 팁, 당신은 오직.drawUI 뷰 내에서, 그렇지 않으면 의미가 없습니다.또한 draw 명령어만 사용할 수 있습니다..fillEllipse등) 내부에서drawUI 뷰의 호출입니다.

  • 본질적인 내용 크기를 올바르게 설정하려는 경우가 거의 확실합니다.소비자 뷰에서 이 기능을 사용하는 방법을 완전히 이해하는 것이 중요합니다. (a) 제약 조건을 사용하는 두 가지 상황에서 (b) 손으로 뷰를 배치하는 것입니다.layoutSubviews다른 관점에서.

  • 큰 고치야는 당신이 할 수 없다는 입니다. draw 어떤 일이 있어도 틀 에서.이와 대조적으로 도면층이 있는 게으른 변수를 사용하여 도형(점, 원 등)을 그리는 경우 공칭 프레임 밖으로 나가면 문제가 없습니다(실제로는 프레임 크기를 0으로 만들어 모든 것이 소비자 코드에 쉽게 집중되도록 하는 경우가 많습니다).하지만 일단 사용하기 시작하면draw프레임 안에 있어야 합니다.그림을 그릴 때까지 "도면의 크기를 알 수 없는" 경우가 있으므로 이는 종종 혼동됩니다.

  • 거대한 고치야는, 당신이 원이나 가장자리를 그릴 때, 초보 프로그래머들이 실수로 그 선의 두께의 절반을 잘랐다는 사실입니다.draw절대로 틀 밖에서 그릴 수 없습니다.원 또는 직사각형을 선 두께의 절반 폭만큼 삽입해야 합니다.

올바른 2022 구문을 가진 일부 코드:

import UIKit
class ExampleDot: UIIView {
    
    // setup ..
    // clipsToBounds = false BUT SEE NOTES
    // backgroundColor = .clear
    
    override var intrinsicContentSize: CGSize {
        return CGSize(width: 40, height: 40)
    }
    
    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        // example of a dot

        ctx.setFillColor(UIColor.black.cgColor)
        ctx.fillEllipse(in: CGRect(x: 0, y: 0, width: 40, height: 40))
        
        // example of a round circle BUT SEE NOTES
        ctx.setStrokeColor(UIColor.systemYellow.cgColor)
        ctx.setLineWidth(2)
        ctx.strokeEllipse(in: CGRect(x: 1, y: 1, width: 40 - 4, height: 40 - 4))

        // example of a smaller inner dot
        ctx.setFillColor(UIColor.white.cgColor)
        ctx.fillEllipse(in: CGRect(x: 10, y: 10, width: 20, height: 20))

    }
}

로드된 뷰에 추가

//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)

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