You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ios-charts的折线图中创建X轴光标?

当然有办法实现这个X轴光标效果啦!虽然iOS Charts(现在也叫Charts库)原生没有直接提供这个功能,但咱们可以基于你提到的Marker功能扩展,再加上自定义绘制来搞定。我给你整理了一套完整的实现方案:

实现步骤

1. 自定义Marker类,记录触摸位置

首先咱们需要一个自定义的Marker,不仅要显示对应的数据信息,还要记录触摸点的X坐标,方便后续绘制垂直光标线:

import Charts

class XAxisCursorMarker: BalloonMarker {
    var touchXPosition: CGFloat = 0.0
    
    override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
        super.refreshContent(entry: entry, highlight: highlight)
        // 保存触摸点的X像素位置,用来绘制垂线
        touchXPosition = highlight.xPx
    }
}

2. 自定义Renderer,绘制垂直光标线

接下来要写一个自定义的折线图渲染器,重写drawExtras方法,在里面绘制贯穿图表的垂直光标线:

class LineChartCursorRenderer: LineChartRenderer {
    private weak var cursorMarker: XAxisCursorMarker?
    
    init(chart: LineChartView, animator: Animator, viewPortHandler: ViewPortHandler, marker: XAxisCursorMarker) {
        super.init(animator: animator, viewPortHandler: viewPortHandler)
        self.chart = chart
        self.cursorMarker = marker
    }
    
    override func drawExtras(context: CGContext) {
        super.drawExtras(context: context)
        
        guard let marker = cursorMarker, marker.touchXPosition != 0 else { return }
        
        // 配置光标线样式:灰色、1pt宽、虚线
        context.setStrokeColor(UIColor.systemGray.cgColor)
        context.setLineWidth(1.0)
        context.setLineDash(phase: 0, lengths: [5, 5])
        
        // 绘制从图表顶部到底部的垂直线
        let topY = viewPortHandler.contentTop
        let bottomY = viewPortHandler.contentBottom
        context.move(to: CGPoint(x: marker.touchXPosition, y: topY))
        context.addLine(to: CGPoint(x: marker.touchXPosition, y: bottomY))
        context.strokePath()
    }
}

3. 配置图表,整合自定义组件

最后在你的ViewController里,把自定义的Marker和Renderer绑定到折线图上:

class ChartViewController: UIViewController {
    @IBOutlet weak var lineChartView: LineChartView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化自定义Marker
        let cursorMarker = XAxisCursorMarker(
            color: UIColor(white: 0.9, alpha: 1.0),
            font: .systemFont(ofSize: 12),
            textColor: .black,
            insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)
        )
        cursorMarker.chartView = lineChartView
        lineChartView.marker = cursorMarker
        
        // 设置自定义Renderer
        let cursorRenderer = LineChartCursorRenderer(
            chart: lineChartView,
            animator: lineChartView.chartAnimator,
            viewPortHandler: lineChartView.viewPortHandler,
            marker: cursorMarker
        )
        lineChartView.renderer = cursorRenderer
        
        // 加载你的折线图数据(示例数据)
        setupSampleChartData()
    }
    
    private func setupSampleChartData() {
        let entries = (0..<15).map { index in
            ChartDataEntry(x: Double(index), y: Double.random(in: 20...100))
        }
        let dataSet = LineChartDataSet(entries: entries, label: "业务数据")
        lineChartView.data = LineChartData(dataSet: dataSet)
    }
}
额外优化建议
  • 如果你想让光标线跟随手指移动更流畅,可以在chartValueSelected和chartValueNothingSelected代理方法里手动触发图表重绘:lineChartView.setNeedsDisplay()
  • 光标线的样式(颜色、宽度、虚实)都可以根据你的UI需求调整,比如把虚线改成实线,或者换个醒目的颜色
  • 如果不需要Marker的气泡提示,也可以把Marker的内容设置为空,只保留记录X坐标的功能

内容的提问来源于stack exchange,提问作者Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:21:35