视差图得到视差
In this tutorial, we’re going to take a look at an interesting SwiftUI Motion effect, and discuss how we can easily apply it to our views by creating our own custom ViewModifier
struct.
在本教程中,我们将看一个有趣的SwiftUI Motion效果,并讨论如何通过创建自己的自定义ViewModifier
结构轻松将其应用于视图。
This effect responds to the device attitude (roll, effect, and yaw) by adjusting the offset of the view it’s applied to. It creates this crazy parallax effect when the user moves their device. Check out the video below for an example.
此效果通过调整应用到视图的偏移量来响应设备的姿态(滚动,效果和偏航)。 当用户移动设备时,它会产生这种疯狂的视差效果。 观看下面的视频作为示例。
Before getting started, please consider subscribing using this link, and if you aren’t reading this on TrailingClosure.com, please come check us out sometime!
在开始之前,请考虑使用此链接进行订阅,如果您未在TrailingClosure.com上阅读此链接 ,请随时联系我们!
构建ParallaxMotionModifier
结构 (Building The ParallaxMotionModifier
Struct)
The ParallaxMotionModifier
struct is going to hold our MotionManager
class. The MotionManager
class is going to be an ObservableObject
which publishes updates on the device attitude (pitch, roll, yaw).
ParallaxMotionModifier
结构将保留我们的MotionManager
类。 MotionManager
类将是一个ObservableObject
,该对象将发布有关设备姿态(俯仰,滚动,偏航)的更新。
Here is the boilerplate code for the ParallaxMotionModifier
struct.
这是ParallaxMotionModifier
结构的样板代码。
import SwiftUI
import CoreMotion
struct ParallaxMotionModifier: ViewModifier {
func body(content: Content) -> some View {
content
}
class MotionManager: ObservableObject {
init() {
}
}
}
设置和接收动作更新 (Setup and Receive Motion Updates)
1. First, we need to add @Published
variables to the MotionManager
class for the pitch and roll. We won't be needing the yaw of the device for this effect.
1.首先,我们需要将@Published
变量添加到MotionManager
类中以进行俯仰和横滚。 为此,我们不需要偏航设备。
class MotionManager: ObservableObject {
@Published var pitch: Double = 0.0
@Published var roll: Double = 0.0
init() {
}
}
2. Next, we create an instance of the CMMotionManager
class to receive motion updates from the device within our class. Additionally, we set the update interval to 60
times per second.
2.接下来,我们创建CMMotionManager
类的实例,以CMMotionManager
该类中的设备接收运动更新。 此外,我们将更新间隔设置为每秒60
次。
class MotionManager: ObservableObject {
@Published var pitch: Double = 0.0
@Published var roll: Double = 0.0
private var motionManager: CMMotionManager
init() {
self.motionManager = CMMotionManager()
self.motionManager.deviceMotionUpdateInterval = 1/60
}
}
3. Finally, we need to subscribe to motion updates and then set the new motion values to our pitch
and roll
variables. That's it for the MotionManager
class.
3.最后,我们需要订阅运动更新,然后将新的运动值设置为我们的pitch
和roll
变量。 MotionManager
类就是这样。
class MotionManager: ObservableObject {
@Published var pitch: Double = 0.0
@Published var roll: Double = 0.0
private var motionManager: CMMotionManager
init() {
self.motionManager = CMMotionManager()
self.motionManager.deviceMotionUpdateInterval = 1/60
self.motionManager.startDeviceMotionUpdates(to: .main) { (motionData, error) in
guard error == nil else {
print(error!)
return
}
if let motionData = motionData {
self.pitch = motionData.attitude.pitch
self.roll = motionData.attitude.roll
}
}
}
}
应用动作更新以查看内容 (Apply Motion Updates to View Content)
Let’s move back to the ParallaxMotionModifier
struct.
让我们回到ParallaxMotionModifier
结构。
1. First at the top of ParallaxMotionModifier
create an instance of the MotionManager
class we just finished building. This will be an @ObservedObject
so that the ParallaxMotionModifier
struct automatically applies the device's motion updates to our content.
1.首先在ParallaxMotionModifier
的顶部创建我们刚刚完成构建的MotionManager
类的实例。 这将是一个@ObservedObject
以便ParallaxMotionModifier
结构自动将设备的运动更新应用于我们的内容。
struct ParallaxMotionModifier: ViewModifier {
@ObservedObject private var motion: MotionManager = MotionManager()
func body(content: Content) -> some View {
content
}
class MotionManager: ObservableObject {
// Motion Manager Definition Here...
}
}
2. Inside the body(content:)
function, apply an offset change to the content using the data from the motionManager
instance.
2.在body(content:)
函数中,使用motionManager
实例中的数据将偏移量应用于内容。
struct ParallaxMotionModifier: ViewModifier {
@ObservedObject private var motion: MotionManager = MotionManager()
func body(content: Content) -> some View {
content
.offset(x: CGFloat(motion.roll), y: CGFloat(motion.pitch))
}
class MotionManager: ObservableObject {
// Motion Manager Definition Here...
}
}
3. If you tried using this modifier now, you wouldn’t see much. The view you apply it to would only move a minuscule amount. This is why we need to create a new variable called magnitude
. We're going to use this when applying our offset to change how much the view moves relative to device motion.
3.如果现在尝试使用此修饰符,则不会看到太多内容。 您将其应用于的视图只会移动很小的量。 这就是为什么我们需要创建一个称为“ magnitude
的新变量的原因。 在应用偏移量时,将使用此值来更改视图相对于设备运动的移动量。
var magnitude: Double
Then apply it inside our offset calculations:
然后将其应用到我们的偏移量计算中:
func body(content: Content) -> some View {
content
.offset(x: CGFloat(motion.roll * magnitude), y: CGFloat(motion.pitch * magnitude))
}
ParallaxMotionModifier
完整代码 (Full Code for ParallaxMotionModifier
)
import SwiftUI
import CoreMotion
struct ParallaxMotionModifier: ViewModifier {
var magnitude: Double
@ObservedObject private var motion: MotionManager = MotionManager()
func body(content: Content) -> some View {
content
.offset(x: CGFloat(motion.roll * magnitude), y: CGFloat(motion.pitch * magnitude))
}
class MotionManager: ObservableObject {
@Published var pitch: Double = 0.0
@Published var roll: Double = 0.0
private var motionManager: CMMotionManager
init() {
self.motionManager = CMMotionManager()
self.motionManager.deviceMotionUpdateInterval = 1/60
self.motionManager.startDeviceMotionUpdates(to: .main) { (motionData, error) in
guard error == nil else {
print(error!)
return
}
if let motionData = motionData {
self.pitch = motionData.attitude.pitch
self.roll = motionData.attitude.roll
}
}
}
}
}
告诉我们你做了什么! (Show us what you made!)
We want to see what you’ve made using this tutorial! Send us pics! Find us on Twitter @TrailingClosure, on Instagram, or email us at howdy@TrailingClosure.com
我们想看看您使用本教程所做的工作! 给我们发图片! 在Twitter @TrailingClosure , Instagram上找到我们,或通过howdy@TrailingClosure.com给我们发送电子邮件
例子 (Examples)
import SwiftUI
struct ParallaxMotionTestView: View {
var body: some View {
ZStack (alignment: .center) {
Color.red
.frame(width: 200, height: 200, alignment: .center)
.cornerRadius(5)
.shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 0)
.modifier(ParallaxMotionModifier(magnitude: 20))
Color.blue
.frame(width: 150, height: 150, alignment: .center)
.cornerRadius(5)
.shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 0)
.modifier(ParallaxMotionModifier(magnitude: 30))
Color.green
.frame(width: 100, height: 100, alignment: .center)
.cornerRadius(5)
.shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 0)
.modifier(ParallaxMotionModifier(magnitude: 40))
Color.orange
.frame(width: 50, height: 50, alignment: .center)
.cornerRadius(5)
.shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 0)
.modifier(ParallaxMotionModifier(magnitude: 50))
}
}
}
翻译自: https://levelup.gitconnected.com/swiftui-parallax-motion-effect-565af67c7894
视差图得到视差