如何使用 ios-图表库在烛台图表中创建自定义限制线标签?

How to create a custom limit line label in candlestick chart using ios-charts library?

我正在使用 "Charts" 库在我的 iOS 应用程序中绘制烛台图表。

我怎样才能像下图那样为限制线添加标签?

Example

据我所知,我必须为 Y 轴创建自定义渲染器并覆盖绘制限制线的方法 and/or Y 轴标签。 到目前为止,我设法实现了这个 screenshot,但是标签没有附加到限制线的右端并且有一个静态位置,这意味着如果我缩放或拖动图表它不会与另一个一起正确移动轴上的标签。截至目前,Y 标签由图表自动生成。

我试着按照这个例子做,但它对我不起作用:Custom view of Limit Line in MPAndroidChart

你能告诉我到底应该怎么做才能使限制线和它的标签在示例图像上看起来像吗? 最好有详细的解释 + 代码,因为我是 iOS 编程的新手。

好的,在对 Y 轴渲染器进行一些修改之后,我设法实现了这种外观和行为。

因此,为了获得那种外观,您必须:

  1. 通过调用 setDrawLabelsEnabled() 并将参数设置为 false
  2. 来禁用默认限制线标签
  3. 对 YAxisRenderer.swift 进行更改。关键是稍微重做 internal func drawYLabels(...) 为每条限制线绘制额外的标签。请参阅下面的代码。
  4. 将偏移量添加到 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()

        }

    }

最终结果如下所示:screenshot

这个实现不是最干净的,但至少对我有用。 如果我的话不清楚,请随时提问。