我正在尝试在我正在开发的应用程序中实现一些有趣的添加,但似乎无法弄清楚如何让动画完全/正确地工作。
目前我有一些看起来像这样的东西:https ://i.imgur.com/95O1Wul.mp4
我正在尝试创建一个全息图,就像您在一些闪亮的游戏卡或一些钞票或那些 VOID 贴纸上看到的那样。
我使用x
设备的位置来确定是否移动渐变的起点和终点。我试图在脑海中弄清楚如何使用这些值来使渐变的起点和终点根据这些值进行移动。如果我合并其他轴,如果设备旋转,它将如何移动。
至于代码,目前我有:
final class ContentViewModel: ObservableObject {
@Published var gyroRotation = CMRotationRate()
private let manager = CMMotionManager()
private var timer: Timer?
func startGyroscope() {
if(manager.isGyroAvailable) {
manager.gyroUpdateInterval = 1.0
manager.startGyroUpdates()
self.timer = Timer(fire: Date(), interval: (1.0/60.0), repeats: true, block: { timer in
if let data = self.manager.gyroData {
self.gyroRotation = data.rotationRate
}
})
RunLoop.current.add(self.timer!, forMode: .default)
}
}
func stopGyroscope() {
if(self.timer != nil) {
self.timer?.invalidate()
self.timer = nil
self.manager.stopGyroUpdates()
}
}
}
Run Code Online (Sandbox Code Playgroud)
struct ContentView: View {
@StateObject var cm = ContentViewModel()
var rotation: CMRotationRate { cm.gyroRotation }
let gridItems = [
GridItem(.flexible(minimum: 40, maximum: 90)),
GridItem(.flexible(minimum: 40, maximum: 90)),
GridItem(.flexible(minimum: 40, maximum: 90)),
GridItem(.flexible(minimum: 40, maximum: 90)),
GridItem(.flexible(minimum: 40, maximum: 90))
]
var body: some View {
LazyVGrid(columns: gridItems, spacing: 30) {
ForEach(0..<60) { _ in
LinearGradient(
colors: [.red, .orange, .yellow, .blue, .purple, .green],
startPoint: rotation.x > 0 ? .leading : .trailing,
endPoint: rotation.x > 0 ? .trailing : .leading
)
.animation(.linear, value: rotation.x)
.frame(width: 50, height: 50)
.mask(
Image("logo")
.resizable()
.scaledToFit()
.opacity(0.3)
)
}
}
.padding(20)
.onAppear { cm.startGyroscope() }
}
}
Run Code Online (Sandbox Code Playgroud)
继续这样做以使其工作,我意识到我不需要 LinearGradient 来制作动画,而是需要 Color 本身:
struct CoreMotion: View {
// -- where the data lives
@ObservedObject var coreMotionVM = CoreMotionViewModel()
let gridItems = [
GridItem(), GridItem(), GridItem(), GridItem()
]
// -- the view
var body: some View {
LazyVGrid(columns: gridItems, spacing: 5) {
ForEach( 0 ..< 60 ) { _ in
coreMotionVM.tintColour
.animation(
.easeInOut,
value: coreMotionVM.roll
)
.frame(width: 60, height: 60)
.padding(.vertical)
.mask(
Image("logo")
.resizable()
.scaledToFit()
.opacity(0.2)
)
}
}
.padding(.horizontal)
.padding(.top)
}
}
Run Code Online (Sandbox Code Playgroud)
final class CoreMotionViewModel: ObservableObject {
// -- what we share
@Published var roll: Double = 0.0
// -- core motion manager
private var manager: CMMotionManager
// -- initialisation
init() {
// -- create the instance
self.manager = CMMotionManager()
// -- how often to get the data
self.manager.deviceMotionUpdateInterval = 1/60
// -- start it on the main thread
self.manager.startDeviceMotionUpdates(to: .main) { motionData, error in
// -- error lets get out of here
guard error == nil else {
print(error!)
return
}
// -- update the data
if let motionData = motionData {
self.roll = motionData.attitude.roll
}
}
}
// cycle to the next point
var tintColour: Color {
switch roll {
case ..<(-1.5):
return .red
case -1.5 ..< -1.0 :
return .orange
case -1.0 ..< -0.5 :
return .yellow
case -0.5 ..< 0.5 :
return .green
case 0.5 ..< 1.0 :
return .blue
case 1.0... :
return .purple
default:
return .pink
}
}
}
Run Code Online (Sandbox Code Playgroud)