Просмотр параллелограмма с использованием UIBezierPath - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь создать пользовательский вид параллелограмма, используя UIBezierPath, но не получаю идеальный.

Ниже приведен мой код пользовательского вида

class CustomView: UIView {
    override func draw(_ rect: CGRect) {
        let offset  = 60.0;
        let path = UIBezierPath()

           path.move(to: CGPoint(x: self.frame.origin.x + CGFloat(offset), y: self.frame.origin.y))
           path.addLine(to: CGPoint(x: self.frame.width + self.frame.origin.x  , y: self.frame.origin.y))
           path.addLine(to: CGPoint(x: self.frame.origin.x + self.frame.width - CGFloat(offset) , y: self.frame.origin.y + self.frame.height))
           path.addLine(to: CGPoint(x: self.frame.origin.x, y: self.frame.origin.y + self.frame.height))


        // Close the path. This will create the last line automatically.
         path.close()
        UIColor.red.setFill()
        path.fill()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        self.layer.mask = shapeLayer;

    }
}

И я создаю вид, используя

let customView = CustomView()
customView.frame = CGRect(origin: CGPoint(x: 10, y: 20), size: CGSize(width: 250, height: 250))
self.view.addSubview(customView)

Но я получил такое представление, и это не идеальный параллелограмм.

enter image description here

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Проблема заключается в использовании frame в пределах draw(_:).Проблема в том, что frame - это «размер и позиция представления в системе координат его суперпредставления » (выделение добавлено).То, как вы визуализируете эту форму в этом представлении, обычно не имеет никакого отношения к тому, где это представление расположено в его суперпредставлении.И если это представление не находится на 0, 0 его суперпредставления, вы можете испытать обрезку.

Но не используйте параметр rect.«В первый раз, когда ваш вид отрисовывается, этот прямоугольник обычно представляет собой все видимые границы вашего вида.Однако во время последующих операций рисования прямоугольник может указывать только часть вашего вида ». Вы рискуете радикально изменить форму, если ОС решит, что нужно обновить только часть вашего CustomView.

Использование bounds, вместо этого, который находится в собственной системе координат представления.И использование minX, minY, maxX и maxY немного упрощает код.

@IBDesignable
class CustomView: UIView {

    @IBInspectable var offset:    CGFloat = 60        { didSet { setNeedsDisplay() } }
    @IBInspectable var fillColor: UIColor = .red      { didSet { setNeedsDisplay() } }

    override func draw(_ rect: CGRect) {
        let path = UIBezierPath()

        path.move(to: CGPoint(x: bounds.minX + offset, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX - offset, y: bounds.maxY))
        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))

        // Close the path. This will create the last line automatically.
        path.close()
        fillColor.setFill()
        path.fill()
    }

}

enter image description here

Asкроме того, я не устанавливаю маску.Если вы анимируете, может показаться неэффективным постоянно сбрасывать маску при каждом вызове draw.Лично я бы просто установил цвет фона вида .clear.Но это не относится к актуальному вопросу.

0 голосов
/ 02 февраля 2019

Как подсказывает @Losiowaty, математика отключена в том смысле, что верхний правый угол выходит за границы кадра.(Не уверен, почему clipToBounds = false не работает; но это всего лишь предложение отладки, а не решение).Попробуйте это:

class CustomView: UIView {
    override func draw(_ rect: CGRect) {
        let offset: CGFloat = 60.0;

        let path = UIBezierPath()

        let width = self.bounds.width - offset

        let upperLeftPoint = CGPoint(x: self.bounds.origin.x + offset, y: self.bounds.origin.y)
        let upperRightPoint = CGPoint(x: self.bounds.origin.x + width, y: self.bounds.origin.y)

        let lowerRightPoint = CGPoint(x: width - offset, y: self.bounds.size.height)
        let lowerLeftPoint = CGPoint(x: self.bounds.origin.x, y: self.bounds.size.height)

        path.move(to: upperLeftPoint)
        path.addLine(to: upperRightPoint)
        path.addLine(to: lowerRightPoint)
        path.addLine(to: lowerLeftPoint)
        path.addLine(to: upperLeftPoint)

        // Close the path. This will create the last line automatically.
        path.close()
        UIColor.red.setFill()
        path.fill()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        self.layer.mask = shapeLayer;
    }
}
...