Как создать собственную метку лимитной линии на свечном графике с помощью библиотеки ios-charts? - PullRequest
0 голосов
/ 25 февраля 2019

Я использую библиотеку "Диаграммы" для рисования свечных диаграмм в своем приложении для iOS.

Как я могу иметь метки для линий ограничения, как на изображении ниже?

Пример

Насколько я понимаю, мне нужно создать пользовательский рендерер для оси Y и методы переопределения для рисования предельных линий и / или меток оси Y.До сих пор мне удавалось добиться этого снимка экрана , но метка не прикреплена к правому концу линии ограничения и имеет статическое положение, что означает, что, если я масштабирую или перетаскиваю диаграмму, она перемещается неправильнодругие метки на оси.На данный момент метки Y автоматически генерируются диаграммой.

Я пытался следовать этому примеру, но у меня это не сработало: Пользовательское представление линии предела в MPAndroidChart

Не могли бы вы сказать мне, что именно я должен сделать, чтобы линия ограничения была похожа на изображение примера?Было бы неплохо иметь подробное объяснение + код, так как я новичок в программировании на iOS.

1 Ответ

0 голосов
/ 19 марта 2019

Хорошо, поэтому после некоторой работы с визуализатором оси Y мне удалось добиться этого вида и поведения.

Таким образом, чтобы получить этот вид, вам необходимо:

  1. Отключить метку линии ограничения по умолчанию, вызвав setDrawLabelsEnabled() с параметром, установленным в false
  2. Внести изменения в YAxisRenderer.swift.Ключ должен слегка переделать internal func drawYLabels(...), чтобы нарисовать дополнительные метки для каждой линии ограничения.См. Код ниже.
  3. Добавьте смещения по осям X и Y (обеим) следующим образом:

    chart.leftAxis.xOffset = 10.0 chart.leftAxis.yOffset = 0.0

Вот фрагмент кода нового internal func drawYLabels(...) метода:

internal func drawYLabels(
        context: CGContext,
        fixedPosition: CGFloat,
        positions: [CGPoint],
        offset: CGFloat,
        textAlign: NSTextAlignment)
    {
        guard
            let yAxis = self.axis as? YAxis
            else { return }

        let labelFont = yAxis.labelFont
        let labelTextColor = yAxis.labelTextColor

        let from = yAxis.isDrawBottomYLabelEntryEnabled ? 0 : 1
        let to = yAxis.isDrawTopYLabelEntryEnabled ? yAxis.entryCount : (yAxis.entryCount - 1)

        for i in stride(from: from, to: to, by: 1)
        {
            let text = yAxis.getFormattedLabel(i)

            ChartUtils.drawText(
                context: context,
                text: "   " + text + "   ",     // Adding some spaces infront and after the label to make some additional space for the bigger "limit line" labels
                point: CGPoint(x: fixedPosition, y: positions[i].y + offset),
                align: textAlign,
                attributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: labelTextColor])


        }

        // This is where we start to draw labels for limit lines
        let myTransformer = self.transformer

        for line in yAxis.limitLines {

            let point = myTransformer!.pixelForValues(x: 0.0, y: line.limit)

            let text = ("  " + line.label + "  ") as NSString       // Adding some spaces to the label in order to make some additional space for the label
            let size = text.size(withAttributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.backgroundColor: UIColor.green])
            var labelPoint: CGPoint?

            // Drawing the triangle in front of the custom label
            let trianglePath = UIBezierPath()
            if yAxis.axisDependency == .right {
                labelPoint = CGPoint(x: fixedPosition + (size.height * 0.3), y: point.y - (size.height / 2))

                if textAlign == .center
                {
                    labelPoint!.x -= size.width / 2.0
                }
                else if textAlign == .right
                {
                    labelPoint!.x -= size.width
                }



                trianglePath.move(to: CGPoint(x: labelPoint!.x - size.height * 0.375, y: labelPoint!.y + (size.height / 2)))
                trianglePath.addLine(to: CGPoint(x: labelPoint!.x, y: labelPoint!.y + (size.height * 0.78)))
                trianglePath.addLine(to: CGPoint(x: labelPoint!.x, y: labelPoint!.y + (size.height * 0.22)))

            } else {

                labelPoint = CGPoint(x: 0.0, y: point.y - (size.height / 2))

                trianglePath.move(to: CGPoint(x: labelPoint!.x + size.width * 1.175, y: labelPoint!.y + (size.height / 2)))
                trianglePath.addLine(to: CGPoint(x: labelPoint!.x + size.width, y: labelPoint!.y + (size.height * 0.78)))
                trianglePath.addLine(to: CGPoint(x: labelPoint!.x + size.width, y: labelPoint!.y + (size.height * 0.22)))
            }

            NSUIGraphicsPushContext(context)

            // Drawing the custom label itself
            (text as NSString).draw(at: labelPoint!, withAttributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.backgroundColor: UIColor.green])

            trianglePath.close()

            // Drawing the triangle with the same color as the limit line and it's label
            line.lineColor.setFill()
            trianglePath.fill()

            NSUIGraphicsPopContext()

        }

    }

Окончательный результат выглядит следующим образом: снимок экрана

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

...