Как нарисовать форму сердца в UIView (iOS)?

Я хочу создать разные формы. Ниже приведено изображение. Вы предложите мне различные формы?

enter image description here

Ответ 1

Пришел к этому, когда я сам пытался нарисовать сердце, основанное на UIBezier, но искал тот, который выглядел немного больше, чем тот, который был на страницах Instagram.

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

(Все это в Swift 3)

Во-первых, здесь расширение UIBezier:

extension UIBezierPath {
    convenience init(heartIn rect: CGRect) {
        self.init()

        //Calculate Radius of Arcs using Pythagoras
        let sideOne = rect.width * 0.4
        let sideTwo = rect.height * 0.3
        let arcRadius = sqrt(sideOne*sideOne + sideTwo*sideTwo)/2

        //Left Hand Curve
        self.addArc(withCenter: CGPoint(x: rect.width * 0.3, y: rect.height * 0.35), radius: arcRadius, startAngle: 135.degreesToRadians, endAngle: 315.degreesToRadians, clockwise: true)

        //Top Centre Dip
        self.addLine(to: CGPoint(x: rect.width/2, y: rect.height * 0.2))

        //Right Hand Curve
        self.addArc(withCenter: CGPoint(x: rect.width * 0.7, y: rect.height * 0.35), radius: arcRadius, startAngle: 225.degreesToRadians, endAngle: 45.degreesToRadians, clockwise: true)

        //Right Bottom Line
        self.addLine(to: CGPoint(x: rect.width * 0.5, y: rect.height * 0.95))

        //Left Bottom Line
        self.close()
    }
}

Вам также нужно добавить это где-нибудь в свой проект, чтобы расширилось расширение degreesToRadians:

extension Int {
    var degreesToRadians: CGFloat { return CGFloat(self) * .pi / 180 }
}

Использование этого так же просто, как инициализация UIBezier так же, как и овал:

let bezierPath = UIBezierPath(heartIn: self.bounds)

В дополнение к этому, я создал класс, который поможет легко отобразить это и управлять определенными функциями. Он будет полностью отображаться в IB, с переопределениями для цвета заливки (с использованием свойства цвета оттенка), независимо от того, хотите ли вы полностью заполнять, цвет штриха и ширину штриха:

@IBDesignable class HeartButton: UIButton {

@IBInspectable var filled: Bool = true
@IBInspectable var strokeWidth: CGFloat = 2.0

@IBInspectable var strokeColor: UIColor?

override func draw(_ rect: CGRect) {
    let bezierPath = UIBezierPath(heartIn: self.bounds)

    if self.strokeColor != nil {
        self.strokeColor!.setStroke()
    } else {
        self.tintColor.setStroke()
    }

    bezierPath.lineWidth = self.strokeWidth
    bezierPath.stroke()

    if self.filled {
        self.tintColor.setFill()
        bezierPath.fill()
    }
}

}

Это класс UIButton, но было бы довольно просто изменить это, если вы не хотите, чтобы это была кнопка.

Вот что это на самом деле выглядит:

Heart Filled

И только с инсультом:

Heart Stroked

Ответ 2

Вы можете попробовать PaintCode.

Нарисуйте его, и PaintCode создаст для вас UIBezierPath.

http://www.paintcodeapp.com/

enter image description here

Ответ 3

Вам нужно создать UIBezierPath. Взгляните на документы: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIBezierPath_class/index.html

и раздел Apple bezier в руководстве по рисованию: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

Вы можете начать с рисования одной дуги с помощью

+bezierPathWithArcCenter: 

а затем добавить другую дугу. Теперь нарисуйте линию до нижнего пика, используя

-addCurveToPoint:controlPoint1:controlPoint2:

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

Наконец, добавьте еще одну строку в начальную точку и закройте путь.

Связанные документы также показывают, как рисовать путь, например. в drawRect. Другой вариант - использовать CAShapeLayer для прямого отображения пути.

Другим решением будет использование программного обеспечения, такого как PaintCode, который позволяет визуально рисовать изображения и генерировать код вместо того, чтобы писать его самостоятельно.

Ответ 4

enter image description here

Итак, как вы можете видеть, есть две простые математические функции. Вам просто нужно нарисовать его в drawRect: Или вы можете легко использовать Framework CorePlot. Полезный пример.

Ответ 5

Другим нарушителям, это расширение для UIBezierPath, чтобы нарисовать сердце.

Извлечен из этого компонента https://github.com/ipraba/EPShapes

 public extension UIBezierPath  {

    func getHearts(originalRect: CGRect, scale: Double) -> UIBezierPath {

    //Scaling will take bounds from the originalRect passed
    let scaledWidth = (originalRect.size.width * CGFloat(scale))
    let scaledXValue = ((originalRect.size.width) - scaledWidth) / 2
    let scaledHeight = (originalRect.size.height * CGFloat(scale))
    let scaledYValue = ((originalRect.size.height) - scaledHeight) / 2

    let scaledRect = CGRect(x: scaledXValue, y: scaledYValue, width: scaledWidth, height: scaledHeight)
    self.moveToPoint(CGPointMake(originalRect.size.width/2, scaledRect.origin.y + scaledRect.size.height))

    self.addCurveToPoint(CGPointMake(scaledRect.origin.x, scaledRect.origin.y + (scaledRect.size.height/4)),
        controlPoint1:CGPointMake(scaledRect.origin.x + (scaledRect.size.width/2), scaledRect.origin.y + (scaledRect.size.height*3/4)) ,
        controlPoint2: CGPointMake(scaledRect.origin.x, scaledRect.origin.y + (scaledRect.size.height/2)) )

    self.addArcWithCenter(CGPointMake( scaledRect.origin.x + (scaledRect.size.width/4),scaledRect.origin.y + (scaledRect.size.height/4)),
        radius: (scaledRect.size.width/4),
        startAngle: CGFloat(M_PI),
        endAngle: 0,
        clockwise: true)

    self.addArcWithCenter(CGPointMake( scaledRect.origin.x + (scaledRect.size.width * 3/4),scaledRect.origin.y + (scaledRect.size.height/4)),
        radius: (scaledRect.size.width/4),
        startAngle: CGFloat(M_PI),
        endAngle: 0,
        clockwise: true)

    self.addCurveToPoint(CGPointMake(originalRect.size.width/2, scaledRect.origin.y + scaledRect.size.height),
        controlPoint1: CGPointMake(scaledRect.origin.x + scaledRect.size.width, scaledRect.origin.y + (scaledRect.size.height/2)),
        controlPoint2: CGPointMake(scaledRect.origin.x + (scaledRect.size.width/2), scaledRect.origin.y + (scaledRect.size.height*3/4)) )
    self.closePath()
    return self
  }
}

Рисует сердце с масштабированием 0,7 (70% от исходного прямоугольника)

введите описание изображения здесь