gpt4 book ai didi

ios - 如何在使用 CAShapeLayer - Swift 绘制的路径上标记点?

转载 作者:行者123 更新时间:2023-11-28 10:20:15 25 4
gpt4 key购买 nike

我在 UIView 中使用 CAShapeLayer 绘制了一条自定义路径。它是一个半圆,上半部分,从左到右绘制。

以下是使用的代码,写在UIView子类中:

func drawSemicircle() {

// drawing an upper half of a circle -> 180 degree to 0 degree, clockwise
let startAngle = CGFloat(M_PI)
let endAngle = CGFloat(0.0)
let centerPoint = CGPointMake(CGRectGetWidth(frame)/2 , CGRectGetHeight(frame))

// path set here
let semirCircleLayer = CAShapeLayer()
let semirCirclePath = UIBezierPath(arcCenter:centerPoint, radius: CGRectGetWidth(frame)/2 - 20.0 , startAngle:startAngle, endAngle:endAngle, clockwise: true)
semirCircleLayer.path = semirCirclePath.CGPath

// layer customisation
semirCircleLayer.fillColor = UIColor.clearColor().CGColor
semirCircleLayer.strokeColor = UIColor(red: 237.0/255.0, green: 236.0/255.0, blue: 236.0/255.0, alpha: 1.0).CGColor
semirCircleLayer.lineWidth = 20.0
semirCircleLayer.lineCap = kCALineCapButt
layer.addSublayer(semirCircleLayer)
}

当前路径如下所示:

Current UI

我想实现的是在条上标记一些点。就像模拟时钟刻度+数字,但不是那么复杂。只需在任何进度级别标记 1 分。所以最终的输出是这样的:

Expected marker

我能得到一些帮助吗?

最佳答案

您需要为刻度线使用另一个 CAShapeLayer,为刻度结束时的文本使用一个 CATextLayer

而不是像 my answer here 那样进行 Core Graphics 绘图确实如此,我建议您使用 100% 层方法以最好地适应您现有的代码。

像这样的东西应该可以解决问题:

func drawSemicircle() {

// drawing an upper half of a circle -> 180 degree to 0 degree, clockwise
let startAngle = CGFloat(M_PI)
let endAngle = CGFloat(0.0)
let centerPoint = CGPoint(x: CGRectGetWidth(frame)*0.5 , y: CGRectGetHeight(frame))
let radius = frame.size.width*0.5 - 80.0 // radius of your arc

// path set here
let semiCircleLayer = CAShapeLayer()
semiCircleLayer.frame = bounds // requried for layer calculations
let semiCirclePath = UIBezierPath(arcCenter:centerPoint, radius:radius, startAngle:startAngle, endAngle:endAngle, clockwise: true)
semiCircleLayer.path = semiCirclePath.CGPath

// layer customisation
semiCircleLayer.fillColor = UIColor.clearColor().CGColor
semiCircleLayer.strokeColor = UIColor(red: 237.0/255.0, green: 236.0/255.0, blue: 236.0/255.0, alpha: 1.0).CGColor
semiCircleLayer.lineWidth = 20.0
semiCircleLayer.lineCap = kCALineCapButt
layer.addSublayer(semiCircleLayer)


// draw graduation (cue the wall of code!)

let graduationLayer = CAShapeLayer() // the graduation layer that'll display the graduation
graduationLayer.frame = semiCircleLayer.bounds

let graduationWidth = CGFloat(4.0) // the width of the graduation
let graduationLength = CGFloat(50.0) // the length of the graduation
let graduationColor = UIColor.redColor() // the color of both the graduation line and text

let startGradRad = radius-semiCircleLayer.lineWidth*0.5 // the starting radius of the graduation
let endGradRad = startGradRad+graduationLength // the ending radius of the graduation

let graduationAngle = CGFloat(M_PI*0.79) // 21% along the arc from the left (0 degrees coresponds to the right hand side of the circle, with the positive angle direction going anti-clocwise (much like a unit circle in maths), so we define 79% along the arc, from the right hand side)

// the starting point of the graduation line. the angles are negative as the arc is effectively drawn upside-down in the UIKit coordinate system.
let startGradPoint = CGPoint(x: cos(-graduationAngle)*startGradRad+centerPoint.x, y: sin(-graduationAngle)*startGradRad+centerPoint.y)
let endGradPoint = CGPoint(x: cos(-graduationAngle)*endGradRad+centerPoint.x, y: sin(-graduationAngle)*endGradRad+centerPoint.y)

// the path for the graduation line
let graduationPath = UIBezierPath()
graduationPath.moveToPoint(startGradPoint) // start point
graduationPath.addLineToPoint(endGradPoint) // end point

graduationLayer.path = graduationPath.CGPath // add path to the graduation shape layer

// configure stroking options
graduationLayer.fillColor = UIColor.clearColor().CGColor
graduationLayer.strokeColor = graduationColor.CGColor
graduationLayer.lineWidth = graduationWidth

// add to semi-circle layer
semiCircleLayer.addSublayer(graduationLayer)

// the font of the text to render at the end of the graduation
let textFont = UIFont.systemFontOfSize(30)

// the text to render at the end of the graduation - do you custom value logic here
let str : NSString = "value"

// default paragraph style
let paragraphStyle = NSParagraphStyle()

// the text attributes dictionary. used to obtain a size of the drawn text in order to calculate its frame
let textAttributes = [NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:textFont]

// size of the rendered text
let textSize = str.sizeWithAttributes(textAttributes)

let xOffset = abs(cos(graduationAngle))*textSize.width*0.5 // the x-offset of the text from the end of the graduation line
let yOffset = abs(sin(graduationAngle))*textSize.height*0.5 // the y-offset of the text from the end of the graduation line

/// the padding between the graduation line and the text
let graduationTextPadding = CGFloat(5.0)

// bit of pythagorus to determine how far away the center of the text lies from the end of the graduation line. multiplying the values together is cheaper than using pow. the text padding is added onto it.
let textOffset = sqrt(xOffset*xOffset+yOffset*yOffset)+graduationTextPadding

// the center of the text to render
let textCenter = CGPoint(x: cos(-graduationAngle)*textOffset+endGradPoint.x, y: sin(-graduationAngle)*textOffset+endGradPoint.y)

// the frame of the text to render
let textRect = CGRect(x: textCenter.x-textSize.width*0.5, y: textCenter.y-textSize.height*0.5, width: textSize.width, height: textSize.height)

let textLayer = CATextLayer()
textLayer.contentsScale = UIScreen.mainScreen().scale // to ensure the text is rendered at the screen scale
textLayer.frame = textRect
textLayer.string = str
textLayer.font = textFont
textLayer.fontSize = textFont.pointSize // required as CATextLayer ignores the font size of the font you pass
textLayer.foregroundColor = graduationColor.CGColor // color of text
graduationLayer.addSublayer(textLayer)
}

输出:

enter image description here

这里有很多代码,因为您必须执行一些额外的逻辑才能计算 CATextLayer 的大小。您可以使用 UILabel 来简化这一点,因为您可以使用 sizeToFit 来计算大小,但这可能会使图层层次结构复杂化。

我已尽力解释每一行代码 - 但如果您仍有疑问,我很乐意回答!

此外,如果您重新构建代码,您可以很容易地允许从类外部更改毕业角度以及其他变量。我在下面的完整项目中提供了一个示例。


完整项目:https://github.com/hamishknight/Dial-View

关于ios - 如何在使用 CAShapeLayer - Swift 绘制的路径上标记点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35909748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com