Нарисовать стрелку-пулю в Core Graphics

Я не хочу изобретать колесо без крайней необходимости, поэтому я хотел посмотреть, как я буду рисовать такую ​​стрелку с помощью Core Graphics:

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

Кто-нибудь знает, как я могу с этим начать? Это то, что у меня есть до сих пор, но он рисует правильный треугольник вместо формы скобки:

    CGPoint origin = CGPointMake(100, 20);
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:origin];
    [path addLineToPoint:CGPointMake(origin.x-10, origin.y-20)];
    [path addLineToPoint:CGPointMake(origin.x-10, origin.y+20)];
    [[UIColor redColor] set];
    [path fill];

person Snowman    schedule 26.04.2012    source источник
comment
Вот где может пригодиться Paintcodeapp.   -  person 0x8badf00d    schedule 26.04.2012
comment
Чёрт возьми, это круто! Не знал, что такое существует ..   -  person Snowman    schedule 26.04.2012
comment
Я бы, вероятно, нарисовал это как фигуру с шестью точками, а не создавал трехточечный путь.   -  person macserv    schedule 26.04.2012
comment
Есть ли какие-нибудь другие классные приложения, такие как Paintcodeapp, которые помогают с рисованием или анимацией?   -  person Snowman    schedule 26.04.2012


Ответы (4)


Если вы рисуете штрихами, как предлагает @NSGod, вам нужно перейти к верхнему или нижнему краю, а затем провести линию к наконечнику стрелки, а затем к нижнему или верхнему краю. Если вы хотите получить угол в 45 градусов, как тот, который вы нарисовали, сумма, которую вы добавляете или вычитаете из координат, должна быть одинаковой.

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

CGPoint origin = CGPointMake(100, 20);

UIBezierPath *path = [UIBezierPath bezierPath];
// Upper tip
[path moveToPoint:CGPointMake(origin.x+20, origin.y-20)];
// Arrow head
[path addLineToPoint:CGPointMake(origin.x, origin.y)];
// Lower tip
[path addLineToPoint:CGPointMake(origin.x+20, origin.y+20)];

[[UIColor redColor] set];
// The line thickness needs to be proportional to the distance from the arrow head to the tips.  Making it half seems about right.
[path setLineWidth:10];
[path stroke];

В результате получилась такая форма.

Стрелка, нарисованная указанным выше кодом

Если вы хотите заполнить, а не обводку - что может потребоваться, если вы хотите очертить стрелку - вам нужно будет нанести 6 точек, а затем замкнуть путь.

person Dondragmer    schedule 26.04.2012
comment
Просто хотел добавить, что в iOS 5 и выше вы можете использовать CGPathCreateCopyByStrokingPath вместо того, чтобы самостоятельно рисовать угловые точки, чтобы получить путь, который вы можете заполнить, а не поглаживать. - person Henri Normak; 03.05.2012

Одна потенциальная часть проблемы заключается в том, что вы использовали fill вместо stroke.

Изменив [path fill] на [path stroke], вы получили бы следующее:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x - 10, origin.y - 20)];
[path addLineToPoint:CGPointMake(origin.x - 10, origin.y + 20)];
[[UIColor redColor] set];
// [path fill];
[path stroke];

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

Это поднимает вопрос о том, что вы имели в виду под точкой origin. Это действительно будет переводиться в точку стрелки, а не в традиционном понимании того, как используется исходная точка (будет означать верхний левый угол рисуемого объекта).

Если вы хотите сохранить свое значение origin, вам нужно изменить код следующим образом:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(origin.x - 20, origin.y - 20)];
[path addLineToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x - 20, origin.y + 20)];
path.lineWidth = 4.0;
[[UIColor redColor] set];
[path stroke];

Или, если вы хотите использовать традиционное значение origin, вы можете использовать:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x + 20, origin.y + 20)];
[path addLineToPoint:CGPointMake(origin.x, origin.y + 20 * 2)];
path.lineWidth = 4.0;
[[UIColor redColor] set];
[path stroke];

Это дает следующее:

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

person NSGod    schedule 26.04.2012
comment
Я тоже пытаюсь это сделать. Мне нужно добавить это в viewDidLoad? - person haris; 17.06.2014

Вот совместимый с Swift 3.0 класс с кредитами на исходный код, взятый из ответа @Dondragmer сверху.

Вы можете изменить:

  • lineHeight: CGFloat
  • lineColor: UIColor
  • direction: Arrow.Direction (перечисление с .up, .down, .left, .right)
class Arrow : UIView {

    enum Direction {
        case up, down, left, right
    }

    var direction : Direction = Direction.right {
        didSet {
            review()
        }
    }

    var lineColor = UIColor.red {
        didSet {
            review()
        }
    }

    var lineWidth : CGFloat = 20 {
        didSet {
            review()
        }
    }

    func review(){
        setNeedsDisplay()
    }


    static func directionToRadians(_ direction: Arrow.Direction) -> CGFloat{
        switch direction {
        case .up:
            return Arrow.degreesToRadians(90)
        case .down:
            return Arrow.degreesToRadians(-90)
        case .left:
            return Arrow.degreesToRadians(0)
        case .right:
            return Arrow.degreesToRadians(180)
        }
    }

    static func degreesToRadians(_ degrees: CGFloat) -> CGFloat {
        return degrees  * CGFloat(M_PI) / 180
    }

    override func draw(_ rect: CGRect) {
        let origin = CGPoint(x: 12, y: self.frame.height / 2)
        let path = UIBezierPath()
        path.lineJoinStyle = CGLineJoin.round
        path.move(to: CGPoint(x: origin.x + self.frame.width * (1/2), y: frame.height - 10))
        path.addLine(to: CGPoint(x: origin.x, y: origin.y))
        path.addLine(to: CGPoint(x: origin.x + self.frame.width * (1/2), y: 10))
        lineColor.set()
        path.lineWidth = lineWidth
        path.stroke()
        self.backgroundColor = UIColor.clear
        self.transform = CGAffineTransform(rotationAngle: Arrow.directionToRadians(self.direction))
    }
}

И теперь вы можете использовать

Он также поддерживает автоматическое размещение.

let arrow = Arrow(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
arrow.lineWidth = 20
arrow.lineColor = UIColor.blue
arrow.direction = .up
person Max Alexander    schedule 02.11.2016
comment
Рад, что прокрутил страницу вниз. Очень хорошо. - person Adam Waite; 11.11.2016

Я не стою перед компьютером, чтобы писать код, но в основном вы создаете CGMutablePath, добавляете, затем делаете

CGContextStrokePath(context);

Вы можете установить ширину обводки и границу линии для достижения желаемого эффекта.

person shein    schedule 26.04.2012
comment
Ну, я знал, что это геометрия, с которой мне нужна помощь - person Snowman; 26.04.2012