Day_Count_Memory_Days/anniversary_Project/Tool/AV_WaveView.swift
2024-07-15 11:52:15 +08:00

138 lines
4.3 KiB
Swift

//
// AV_WaveView.swift
// anniversary_Project
//
// Created by 16 on 2024/7/8.
//
import UIKit
class AV_WaveView: UIView {
private var waveLayers: [CAShapeLayer] = []
private var waveHeight: CGFloat = 10.0
private var waveLength: CGFloat = 200.0
private var waveSpeed: CGFloat = 0.05
private var waveOffset: CGFloat = 0.0
private var wavePositionY: CGFloat = 0.0
private var totalCapacity: CGFloat = 0.0
private var currentVolume: CGFloat = 0.0
private var timer: Timer?
override init(frame: CGRect) {
super.init(frame: frame)
setupWaveLayers()
setupMaskLayer()
startWaveAnimation()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupWaveLayers()
setupMaskLayer()
startWaveAnimation()
}
private func setupWaveLayers() {
let colors = [UIColor.hexSting(color: "#96D3FF", alpha: 1).cgColor,
UIColor.hexSting(color: "#62BFFF", alpha: 1).cgColor]
for color in colors {
let waveLayer = CAShapeLayer()
waveLayer.fillColor = color
layer.addSublayer(waveLayer)
waveLayers.append(waveLayer)
}
}
private func setupMaskLayer() {
let maskLayer = CAShapeLayer()
let path = UIBezierPath(rect: bounds)
maskLayer.path = path.cgPath
layer.mask = maskLayer
}
private func startWaveAnimation() {
timer = Timer.scheduledTimer(timeInterval: 1.0 / 30.0, target: self, selector: #selector(updateWave), userInfo: nil, repeats: true)
}
@objc private func updateWave() {
waveOffset += waveSpeed
for (index, waveLayer) in waveLayers.enumerated() {
let amplitude = waveHeight * (1.2 - 0.2 * CGFloat(index))
let path = createWavePath(offset: waveOffset + CGFloat(index) * 0.3, amplitude: amplitude)
waveLayer.path = path.cgPath
}
}
private func createWavePath(offset: CGFloat, amplitude: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let width = bounds.width
let height = bounds.height
let midY = height * wavePositionY
path.move(to: CGPoint(x: 0, y: midY))
for x in stride(from: 0.0, to: Double(width), by: 1.0) {
let relativeX = CGFloat(x) / waveLength * .pi * 2
let y = sin(relativeX + offset) * amplitude + midY
path.addLine(to: CGPoint(x: CGFloat(x), y: y))
}
path.addLine(to: CGPoint(x: width, y: height))
path.addLine(to: CGPoint(x: 0, y: height))
path.close()
return path
}
func setTotalCapacity(_ capacity: CGFloat) {
totalCapacity = capacity
currentVolume = 0
wavePositionY = 1.0
updateWavePosition(animated: false)
}
func drinkWater(_ volume: CGFloat) {
currentVolume += volume
if currentVolume > totalCapacity {
currentVolume = totalCapacity
}
let newPositionY = 1.0 - (currentVolume / totalCapacity)
updateWavePosition(animated: true, targetPositionY: newPositionY)
}
func setCurrentVolume(_ volume: CGFloat) {
currentVolume = volume
if currentVolume > totalCapacity {
currentVolume = totalCapacity
} else if currentVolume < 0 {
currentVolume = 0
}
let newPositionY = 1.0 - (currentVolume / totalCapacity)
updateWavePosition(animated: true, targetPositionY: newPositionY)
}
private func updateWavePosition(animated: Bool, targetPositionY: CGFloat? = nil) {
let newPositionY = targetPositionY ?? (1.0 - (currentVolume / totalCapacity))
if animated {
UIView.animate(withDuration: 3.0, delay: 0, options: [.curveEaseInOut], animations: {
self.wavePositionY = newPositionY
self.layer.setNeedsDisplay()
}, completion: { finished in
if finished {
print("Animation completed.")
}
})
} else {
wavePositionY = newPositionY
layer.setNeedsDisplay()
}
}
deinit {
timer?.invalidate()
}
}