i am trying to add an overlay (marker view) along side my path created with UIBezierPath. i can achieve it with hardcoded values comparing x's and y's of the graph. but problem is this is getting too much hardcoded as there will be different values expected and i cannot (should not) do such hardcoded.
center.x + outerRadius * cos(startAngle)
i get the location of the next part of the chart by this, but i cannot place my UIView on a right place.
is there anyway i can place a uiview on a UIBezierPath and adjust its direction as per needed (like left right or below or top) of the chart ?
i am trying to add an overlay (marker view) along side my path created with UIBezierPath. i can achieve it with hardcoded values comparing x's and y's of the graph. but problem is this is getting too much hardcoded as there will be different values expected and i cannot (should not) do such hardcoded.
center.x + outerRadius * cos(startAngle)
i get the location of the next part of the chart by this, but i cannot place my UIView on a right place.
is there anyway i can place a uiview on a UIBezierPath and adjust its direction as per needed (like left right or below or top) of the chart ?
Share Improve this question asked Mar 13 at 9:37 IDevIDev 1,2251 gold badge11 silver badges25 bronze badges 2 |1 Answer
Reset to default 1As far as I can tell, your UIBezierPath
s are parts of your outer circle. I assume you draw them using startAngle
and endAngle
. I think you could draw an imaginary circle (which has the same center as yours, and radius of (your inner circle + width of your outer UIBezierPath
) / 2 and put your UILabel
's corner on it.
Here's my implementation of an imaginary circle:
import UIKit
class CircleSliderViewController: UIViewController {
private let circleLayer = CAShapeLayer()
private let slider = UISlider()
private let movingLabel = UILabel()
private let circleRadius: CGFloat = 120
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupCircle()
setupSlider()
setupLabel()
updateLabelPosition(angle: 0)
}
private func setupCircle() {
let center = view.center
let circlePath = UIBezierPath(arcCenter: center,
radius: circleRadius,
startAngle: 0,
endAngle: 2 * .pi,
clockwise: true)
circleLayer.path = circlePath.cgPath
circleLayer.strokeColor = UIColor.gray.cgColor
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineWidth = 2
view.layer.addSublayer(circleLayer)
}
private func setupSlider() {
slider.minimumValue = 0
slider.maximumValue = 360
slider.value = 0
slider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged)
slider.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(slider)
NSLayoutConstraint.activate([
slider.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -40),
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40),
slider.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40)
])
}
private func setupLabel() {
movingLabel.text = "Label"
movingLabel.textAlignment = .center
movingLabel.backgroundColor = UIColor.systemBlue
movingLabel.textColor = UIColor.white
movingLabel.layer.cornerRadius = 8
movingLabel.clipsToBounds = true
movingLabel.frame.size = CGSize(width: 60, height: 30)
view.addSubview(movingLabel)
}
@objc private func sliderChanged(_ sender: UISlider) {
let angle = CGFloat(sender.value) * .pi / 180
updateLabelPosition(angle: angle)
}
private func updateLabelPosition(angle: CGFloat) {
let center = view.center
let xPosition = center.x + (circleRadius + movingLabel.frame.width / 2) * cos(angle)
let yPosition = center.y + (circleRadius + movingLabel.frame.height / 2) * sin(angle)
movingLabel.center = CGPoint(x: xPosition, y: yPosition)
}
}
currentPoint
to get the last point in the path. So this might be a way of determining a suitable position for a label. However, one line of code doesn't give much to go on. Please provide a complete working example. – Benzy Neez Commented Mar 13 at 9:43