Search code examples
iosswiftios-charts

Draw rectangle to not fall off screen during scroll


I am using the charts library with a marker rectangle that displays data depending on where the crosshairs is at. Right now it is centered above the y-axis line, centered on the x-axis line. But if you select values too far left/right/up/down, the rectangle will get cut off and fall off the screen. How can I make it where if it is going to get cut off on the right, it will shift to still being above the y axis line but to the LEFT of the x-axis line instead of centered on it. Likewise if it would get cut off on the left, top, bottom, but with their respective opposite directions.

    override func draw(context: CGContext, point: CGPoint) {
        // custom padding around text
        let labelWidth = labelText.size(withAttributes: attrs).width + 20
        // if you modify labelHeigh you will have to tweak baselineOffset in attrs
        let labelHeight = labelText.size(withAttributes: attrs).height + 5 //Me


        // place pill above the marker, centered along x
        var rectangle = CGRect(x: point.x, y: point.y, width: labelWidth, height: labelHeight)// + 10) Me
        rectangle.origin.x -= rectangle.width / 2.0
        let spacing: CGFloat = 10
        rectangle.origin.y -= rectangle.height + spacing

        // rounded rect
        let clipPath = UIBezierPath(roundedRect: rectangle, cornerRadius: 6.0).cgPath
        context.addPath(clipPath)
        context.setFillColor(color.cgColor)
        context.setStrokeColor(color.darker(by: 10)!.cgColor)



//        context.setStrokeColor(color.)
        context.closePath()
        context.drawPath(using: .fillStroke)

        // add the text
        labelText.draw(with: rectangle, options: .usesLineFragmentOrigin, attributes: attrs, context: nil)  //usesLineFragmentOrigin
    }

Solution

  • Solved with a stupid easy fix seen here. Just checked if the origins crossed over the respective values and moved them accordingly since this code gets called with every movement of the crosshair on the plot.

    var rectangle = CGRect(x: point.x, y: point.y, width: labelWidth, height: labelHeight)// + 10) Me
        rectangle.origin.x -= rectangle.width / 2.0
    
        if rectangle.origin.x + (rectangle.width) > UIScreen.main.bounds.width {
            rectangle.origin.x -= (rectangle.width / 2.0) + 10
        } else if rectangle.origin.x < 0 {
            rectangle.origin.x += (rectangle.width / 2.0) + 10
        }
    
        let spacing: CGFloat = 10
        rectangle.origin.y -= rectangle.height + spacing
    
        if rectangle.origin.y < spacing {
            rectangle.origin.y += 20 + (rectangle.height)
        }