gpt4 book ai didi

ios - 使用 uibezierpath 制作一个非常简单的图表

转载 作者:行者123 更新时间:2023-11-28 06:18:23 25 4
gpt4 key购买 nike

我的问题是

我想创建一个具有特定值的简单折线图。这是在 mainviewcontroller 中的一个 View 中完成的。我创建了一个名为图表的 UIview。当从 API 检索数据时,我将数据传递给图表。我想出了如何绘制轴,但我现在被卡住了。我在谷歌上找不到任何关于如何设置间隔标签和动态显示点的信息。

  • draw the xasis and its labels.
  • draw the dots in the graph.

我的解决方案

  • i figured out how to do all the things i asked for.

我现在的代码:

class ChartView: UIView {

//some variables
var times: [String] = []
var AmountOfRain: [Double] = []
let pathy = UIBezierPath()
let pathx = UIBezierPath()
var beginwitharray = Array<CGFloat>()

// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code

//draw the y line
pathy.move(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathy.lineWidth = 1.0
pathy.stroke()

//draw the x line
pathx.move(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: frame.size.width - 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathx.lineWidth = 1.0
pathx.stroke()

//when the data arrives form the SUPER slow duienradar API refresh it with the data
if beginwitharray != []{
//remove the label retriving data
let label = viewWithTag(1)
DispatchQueue.main.sync {
label?.removeFromSuperview()
}
//create the dots in the graph
var point = CGPoint()
//simple way to do 2 loop in 1 loop.
var intforbeginarray = 0
let stoke = UIBezierPath()
//get the first 6 itmes out of the rain array cuz of space issues
let first6aumountarray = AmountOfRain[0...5]
stoke.move(to: CGPoint(x: 30, y: self.frame.size.height - 30))

//loop trough the data in the amounts array
for amount in first6aumountarray{
//determen the hight of the dot
let InitialHeight = (CGFloat(amount) * (self.frame.size.height - 30))/6
let pointHeight = (frame.size.height - 30) - InitialHeight

//make the point so we can draw it using UIbezierpath()
point = CGPoint(x: beginwitharray[intforbeginarray] + 20, y: pointHeight)
intforbeginarray += 1

//create the dot
let dot = UIBezierPath()
dot.addArc(withCenter: point, radius: CGFloat(5), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true)
UIColor.black.setFill()
dot.lineWidth = 30
dot.fill()

//create the line between dots will give a warning on the last one cuz the last one doenst go anyway
stoke.addLine(to: point)
stoke.move(to: point)
stoke.lineWidth = 1
UIColor.black.setStroke()
}
//make the strokes
stoke.stroke()
}
}
func getvalues(RainData: [Double], TimesData:[String]){

//assing the data to the subview
self.AmountOfRain = RainData
self.times = TimesData

//xaxis values
let maxint = [0, 1, 2, 3, 4, 5, 6]

//calculate the hight spacing to fit the graph
let heightperstep = ((self.frame.size.height - 5)/6)-5
var beginheight = self.frame.size.height - 35

//calculate the width spacing to fit the graph
let widthperstep = ((self.frame.size.width - 5)/6)-5
var beginwith = CGFloat(30)

//extra check to see if we have data at all.
if times != []{
//get the first 6 items out of the times array for use in our graph
let first6 = times[0...5]
//draw the label on the main queue
DispatchQueue.main.sync {
//draw the xaxis labels accroding to the spacing
for number in maxint{
let label = UILabel(frame: CGRect(x: 5, y: beginheight, width: 25, height: 15))
label.text = "\(number)"
self.addSubview(label)
beginheight = beginheight - heightperstep
}
//draw the yaxis labels according to the spacing
for time in first6{
let label = UILabel(frame: CGRect(x: beginwith, y: self.frame.size.height - 20, width: 55, height: 15))
label.text = time
self.addSubview(label)
beginwitharray.append(beginwith)
beginwith = beginwith + widthperstep
}
}
}
//redrawthe graph with new data.
setNeedsDisplay()
}}

如有任何帮助,我们将不胜感激。我也不能使用 lib 或 pod,因为这是一个学校项目,我需要创建一个简单的图表。

编辑:

完成了我的代码,清除了运行这段代码时的错误

我首先做的是绘制 x 轴和 y 轴。在此之后,我考虑了雨量数据的合理值。事实证明,这实际上不可能高于 6。因为我可以在空间中放置大约 6 个标签,所以我的步骤很容易下降 1 直到我达到 0。我所做的计算是针对我的特定帧高度的。在我弄清楚这一切以及 y 轴的填充之后。这是一个弄清楚如何将点放在正确位置的问题。因为我已经在 beginwitharray 中有了数据,所以我只需要计算高度。然后它只是简单地遍历数据并绘制每个点。然后我只需要使用 uibezierpath 连接点。

我希望我的麻烦能为阅读我的做法的人节省很多时间。

最佳答案

这可能会有帮助:Draw Graph curves with UIBezierPath

基本上您需要做的是,对于您拥有的每个数据集,您需要知道值的 y 轴范围,并根据这些范围为每个值分配一个 CGFloat 值(在您的情况下,英寸雨量需要与某些 CGFloat 值)。假设你有你的集合 amountOfRain = [0.1, 1.3, 1.5, 0.9, 0.1, 0] 所以你的范围是 var rangeY = amountOfRain.max() - amountOfRain.min()。现在让我们找出第一个数据点 0.1 应该在图表上的什么位置,方法是将英寸雨量转换为对应于您已经绘制的轴的 CGFloat 值,这个等式只是基本代数:让 y1 = (amountOfRain [0]/rangeY)*((frame.size.height-30) - 10) + 10 现在看起来你的雨水样本是固定间隔的所以也许 让 x1:CGFloat = 10 现在你可以在对应于(x1,y1)的CGPoint处添加一个点或其他东西。如果您对所有数据点执行此操作,它会创建一个图表,其中最大值位于图表顶部,最小值位于图表底部。祝你好运!

关于ios - 使用 uibezierpath 制作一个非常简单的图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44409400/

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