我一直在努力了解如何在iOS中绘制Siri的波形效果,并且遇到了this伟大的存储库。 最终结果如下:
但是我很难理解生成波形的代码发生了什么。我可以生成一个静态正弦波,但是,我似乎并不理解。
特别是当我们计算y的值时,为什么它必须是:
let y = scaling * maxAmplitude * normedAmplitude *
sin(CGFloat(2 * M_PI) * self.frequency * (x / self.bounds.width) + self.phase) + self.bounds.height/2.0
源代码:
//MARK : Properties
let density : CGFloat = 1
let frequency : CGFloat = 1.5
var phase :CGFloat = 0
var phaseShift:CGFloat = -0.15
var numberOfWaves:Int = 6
var primaryLineWidth:CGFloat = 1.5
var idleAmplitude:CGFloat = 0.01
var waveColor:UIColor = UIColor.white
var amplitude:CGFloat = 1.0 {
didSet {
amplitude = max(amplitude, self.idleAmplitude)
self.setNeedsDisplay()
}
}
方法
override open func draw(_ rect: CGRect) {
// Convenience function to draw the wave
func drawWave(_ index:Int, maxAmplitude:CGFloat, normedAmplitude:CGFloat) {
let path = UIBezierPath()
let mid = self.bounds.width/2.0
path.lineWidth = index == 0 ? self.primaryLineWidth : self.secondaryLineWidth
for x in Swift.stride(from:0, to:self.bounds.width + self.density, by:self.density) {
// Parabolic scaling
let scaling = -pow(1 / mid * (x - mid), 2) + 1
// The confusing part /////////////////////////////////////////
let y = scaling * maxAmplitude * normedAmplitude *
sin(CGFloat(2 * M_PI) * self.frequency * (x / self.bounds.width) + self.phase)
+ self.bounds.height/2.0
//////////////////////////////////////////////////////////////////
if x == 0 {
path.move(to: CGPoint(x:x, y:y))
} else {
path.addLine(to: CGPoint(x:x, y:y))
}
}
path.stroke()
}
let context = UIGraphicsGetCurrentContext()
context?.setAllowsAntialiasing(true)
self.backgroundColor?.set()
context?.fill(rect)
let halfHeight = self.bounds.height / 2.0
let maxAmplitude = halfHeight - self.primaryLineWidth
for i in 0 ..< self.numberOfWaves {
let progress = 1.0 - CGFloat(i) / CGFloat(self.numberOfWaves)
let normedAmplitude = (1.5 * progress - 0.8) * self.amplitude
let multiplier = min(1.0, (progress/3.0*2.0) + (1.0/3.0))
self.waveColor.withAlphaComponent(multiplier * self.waveColor.cgColor.alpha).set()
drawWave(i, maxAmplitude: maxAmplitude, normedAmplitude: normedAmplitude)
}
self.phase += self.phaseShift
}
两个for循环看起来都很数学,我不知道那里发生了什么。 提前谢谢。