62
задан 4 November 2016 в 09:30

6 ответов

Это не было давно, что я даже не знал, как объявить, что BГ©zier, уже не говоря о знают, как использовать пути BГ©zier для создания пользовательской формы. Следующее - то, что я изучил. Оказывается, что они не так страшны, как они кажутся сначала.

, Как потянуть путь BГ©zier в пользовательском представлении

, Это основные шаги:

  1. Дизайн схема формы Вы хотите.
  2. Делят путь схемы к сегментам строк, дуг и кривых.
  3. Сборка тот путь программно.
  4. Тянут путь или в drawRect или использование CAShapeLayer.

контур фигур Дизайна

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

enter image description here

Делят путь к сегментам

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

Вот то, на что был бы похож наш дизайн в качестве примера:

enter image description here

  • Черный линейные сегменты
  • Голубой, сегменты дуги
  • Красный, кривые
  • , Оранжевые точки являются контрольными точками для кривых
  • , точки Green являются точками между сегментами контура
  • , Пунктирные линии показывают ограничительный прямоугольник
  • , Темно-синие числа являются сегментами в порядке, что они будут добавлены программно

Сборка путь программно

, Мы произвольно запустим в левом нижнем угле и работе по часовой стрелке. Я буду использовать сетку в изображении для получения значений X и Y для точек. Я буду hardcode все здесь, но конечно Вы не сделали бы этого в реальном проекте.

базовый процесс:

  1. Создают новое UIBezierPath
  2. , Выбирают начальную точку на пути с moveToPoint
  3. сегменты Add к пути
    • строка: addLineToPoint
    • дуга: addArcWithCenter
    • кривая: addCurveToPoint
  4. Близко путь с [1 112]

Вот код для создания пути в изображении выше.

func createBezierPath() -> UIBezierPath {

    // create a new path
    let path = UIBezierPath()

    // starting point for the path (bottom left)
    path.move(to: CGPoint(x: 2, y: 26))

    // *********************
    // ***** Left side *****
    // *********************

    // segment 1: line
    path.addLine(to: CGPoint(x: 2, y: 15))

    // segment 2: curve
    path.addCurve(to: CGPoint(x: 0, y: 12), // ending point
        controlPoint1: CGPoint(x: 2, y: 14),
        controlPoint2: CGPoint(x: 0, y: 14))

    // segment 3: line
    path.addLine(to: CGPoint(x: 0, y: 2))

    // *********************
    // ****** Top side *****
    // *********************

    // segment 4: arc
    path.addArc(withCenter: CGPoint(x: 2, y: 2), // center point of circle
        radius: 2, // this will make it meet our path line
        startAngle: CGFloat(M_PI), // π radians = 180 degrees = straight left
        endAngle: CGFloat(3*M_PI_2), // 3π/2 radians = 270 degrees = straight up
        clockwise: true) // startAngle to endAngle goes in a clockwise direction

    // segment 5: line
    path.addLine(to: CGPoint(x: 8, y: 0))

    // segment 6: arc
    path.addArc(withCenter: CGPoint(x: 8, y: 2),
                          radius: 2,
                          startAngle: CGFloat(3*M_PI_2), // straight up
        endAngle: CGFloat(0), // 0 radians = straight right
        clockwise: true)

    // *********************
    // ***** Right side ****
    // *********************

    // segment 7: line
    path.addLine(to: CGPoint(x: 10, y: 12))

    // segment 8: curve
    path.addCurve(to: CGPoint(x: 8, y: 15), // ending point
        controlPoint1: CGPoint(x: 10, y: 14),
        controlPoint2: CGPoint(x: 8, y: 14))

    // segment 9: line
    path.addLine(to: CGPoint(x: 8, y: 26))

    // *********************
    // **** Bottom side ****
    // *********************

    // segment 10: line
    path.close() // draws the final line to close the path

    return path
}

Примечание: Часть вышеупомянутого кода может быть уменьшена путем добавления строки и дуги в единственной команде (так как дуга имеет подразумеваемую начальную точку). См. здесь для получения дополнительной информации.

Тянут путь

, Мы можем потянуть путь или в слое или в [1 113].

Метод 1: Потяните путь в уровне

, Наш пользовательский класс похож на это. Мы добавляем наш путь Bezier к новому CAShapeLayer, когда представление инициализируется.

import UIKit
class MyCustomView: UIView {

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

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

    func setup() {

        // Create a CAShapeLayer
        let shapeLayer = CAShapeLayer()

        // The Bezier path that we made needs to be converted to 
        // a CGPath before it can be used on a layer.
        shapeLayer.path = createBezierPath().cgPath

        // apply other properties related to the path
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.lineWidth = 1.0
        shapeLayer.position = CGPoint(x: 10, y: 10)

        // add the new layer to our custom view
        self.layer.addSublayer(shapeLayer)
    }

    func createBezierPath() -> UIBezierPath {

        // see previous code for creating the Bezier path
    }
}

И создание нашего представления в Контроллере Представления как это

override func viewDidLoad() {
    super.viewDidLoad()

    // create a new UIView and add it to the view controller
    let myView = MyCustomView()
    myView.frame = CGRect(x: 100, y: 100, width: 50, height: 50)
    myView.backgroundColor = UIColor.yellow
    view.addSubview(myView)

}

Мы добираемся...

enter image description here

Хм, это является немного маленьким потому что я hardcoded все числа в. Я могу увеличить масштаб размера пути, тем не менее, как это:

let path = createBezierPath()
let scale = CGAffineTransform(scaleX: 2, y: 2)
path.apply(scale)
shapeLayer.path = path.cgPath

enter image description here

Метод 2: Потяните путь в [1 115]

Используя [1 116], медленнее, чем рисование к слою, таким образом, это не рекомендуемый метод, если Вам не нужен он.

Вот пересмотренный код для нашего пользовательского представления:

import UIKit
class MyCustomView: UIView {

    override func draw(_ rect: CGRect) {

        // create path (see previous code)
        let path = createBezierPath()

        // fill
        let fillColor = UIColor.white
        fillColor.setFill()

        // stroke
        path.lineWidth = 1.0
        let strokeColor = UIColor.blue
        strokeColor.setStroke()

        // Move the path to a new location
        path.apply(CGAffineTransform(translationX: 10, y: 10))

        // fill and stroke the path (always do these last)
        path.fill()
        path.stroke()

    }

    func createBezierPath() -> UIBezierPath {

        // see previous code for creating the Bezier path
    }
}

, который дает нам тот же результат...

enter image description here

Дальнейшее исследование

я действительно рекомендую смотреть на следующие материалы. Они - то, что наконец сделало пути BГ©zier понятными для меня. (И учил меня, как объявить его:/Л€bЙ› zi eЙЄ/.)

228
ответ дан 31 October 2019 в 13:01

Было бы легче, если Вы будете использовать CAShapeLayer, как это:

CAShapeLayer *shapeView = [[CAShapeLayer alloc] init];

И набор path:

[shapeView setPath:[self createPath].CGPath];

Наконец добавляют его:

[[self.view layer] addSublayer:shapeView];
53
ответ дан 31 October 2019 в 13:01

Можно использовать CAShapeLayer, чтобы сделать это.

Как это...

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [self createPath].CGPath;
shapeLayer.strokeColor = [UIColor redColor].CGColor; //etc...
shapeLayer.lineWidth = 2.0; //etc...
shapeLayer.position = CGPointMake(100, 100); //etc...
[self.layer addSublayer:shapeLayer];

Это затем добавит и потянет путь, не имея необходимость переопределять drawRect.

15
ответ дан 31 October 2019 в 13:01

Существует несколько способов выполнить то, чего Вы желаете. Те, которых я видел больше всего: переопределите drawRect, вовлеките Вашу форму в CAShapeLayer и затем добавьте его, поскольку подуровень к Вашему представлению, или тянут Ваш путь на другой контекст , сохраняют это как изображение и затем добавляют его к Вашему представлению.

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

5
ответ дан 31 October 2019 в 13:01

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

Слои фигуры, вероятно, чтобы дать Вам лучшую производительность, чем переопределение drawRect.

, Если Вы хотите потянуть свой путь сами затем да, необходимо переопределить drawRect для пользовательского класса представления.

2
ответ дан 31 October 2019 в 13:01

Да, необходимо переопределить drawrect, если Вы хотите потянуть что-нибудь. Создание UIBezierPath может быть сделано где угодно, Но потянуть что-то необходимо сделать это в drawrect метод

, необходимо звонить setNeedsDisplay при переопределении drawRect в подклассе UIView, который является в основном пользовательским представлением, тянущим что-то на экране, как строки, изображение, прямоугольник.

1
ответ дан 31 October 2019 в 13:01

Другие вопросы по тегам:

Похожие вопросы: