问题
I am drawing one period of a sine wave with:
let width = rect.width
let height = rect.height
let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)
let path = UIBezierPath()
path.move(to: origin)
for angle in stride(from: 5.0, through: 360.0, by: 5.0) {
let x = origin.x + CGFloat(angle/360.0) * width * graphWidth
let y = origin.y - CGFloat(sin(angle/180.0 * Double.pi)) * height * amplitude
path.addLine(to: CGPoint(x: x, y: y))
}
Globals.sharedInstance.palleteGlowGreen.setStroke()
path.stroke()
How would I:
- Draw multiple periods for the same width (now its 0-360)
- Change number 1 (num of periods) dynamically so you see the wave squeezing.
回答1:
Just multiply the angle by periods:
@IBDesignable
class SineWaveView: UIView {
@IBInspectable
var graphWidth: CGFloat = 0.90 { didSet { setNeedsDisplay() } }
@IBInspectable
var amplitude: CGFloat = 0.20 { didSet { setNeedsDisplay() } }
@IBInspectable
var periods: CGFloat = 1.0 { didSet { setNeedsDisplay() } }
override func draw(_ rect: CGRect) {
let width = bounds.width
let height = bounds.height
let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)
let path = UIBezierPath()
path.move(to: origin)
for angle in stride(from: 5.0, through: 360.0 * periods, by: 5.0) {
let x = origin.x + angle/(360.0 * periods) * width * graphWidth
let y = origin.y - sin(angle/180.0 * .pi) * height * amplitude
path.addLine(to: CGPoint(x: x, y: y))
}
Globals.sharedInstance.palleteGlowGreen.setStroke()
path.stroke()
}
}
By the way, by making a change in periods call setNeedsDisplay, that means that when you update periods, the graph will be automatically redrawn.
And, rather than iterating through degrees, but then converting everything back to radians, I might just stay in radians:
override func draw(_ rect: CGRect) {
let width = bounds.width
let height = bounds.height
let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)
let maxAngle: CGFloat = 2 * .pi * periods
let iterations = Int(min(1000, 100 * periods))
let point = { (angle: CGFloat) -> CGPoint in
let x = origin.x + angle/maxAngle * width * self.graphWidth
let y = origin.y - sin(angle) * height * self.amplitude
return CGPoint(x: x, y: y)
}
let path = UIBezierPath()
path.move(to: point(0))
for i in 1 ... iterations {
path.addLine(to: point(maxAngle * CGFloat(i) / CGFloat(iterations)))
}
Globals.sharedInstance.palleteGlowGreen.setStroke()
path.stroke()
}
来源:https://stackoverflow.com/questions/40411198/draw-sine-wave-with-frequency