【SwiftUI模块】0019、SwiftUI搭建一个图片带有传感器的视觉差效果

SwiftUI模块系列 - 已更新19篇
SwiftUI项目 - 已更新1个项目
往期Demo源码下载

技术:SwiftUI、SwiftUI3.0、传感器、图片视觉差、图片传感器
运行环境:
SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max

概述

使用SwiftUI搭建一个图片带有传感器的视觉差效果

详细

一、运行效果

请添加图片描述

二、项目结构图

在这里插入图片描述

三、程序实现 - 过程 - 需要真机调试

思路

  1. 先做出一个蒙版
  2. 做一个区域的图片
    在这里插入图片描述
  3. 初始化传感器 - 传递偏移的值,进行传感器的设置,进行高光部分偏移

1.创建一个项目命名为 MotionParallax

在这里插入图片描述
在这里插入图片描述

1.1.引入资源文件和颜色

颜色
背景1张

在这里插入图片描述

扫描二维码关注公众号,回复: 14508908 查看本文章

2. 创建一个虚拟文件New Group 命名为 View

在这里插入图片描述
在这里插入图片描述

3. 创建一个虚拟文件New Group 命名为 ViewModel

在这里插入图片描述
在这里插入图片描述

4. 创建一个文件New File 选择SwiftUI View类型 命名为Home

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5. 创建一个文件New File 选择SwiftUI View类型 命名为MotionObserver 并且继承ObservableObject

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

6. 创建一个文件New File 选择SwiftUI View类型 命名为OffsetModifier

在这里插入图片描述

Code

ContentView - 主窗口

主要是展示主窗口Home

//
//  ContentView.swift
//  Shared
//
//  Created by lyh on 2022/8/31.
//

import SwiftUI

struct ContentView: View {
    
    
    var body: some View {
    
    
        Home()
    }
}

struct ContentView_Previews: PreviewProvider {
    
    
    static var previews: some View {
    
    
        ContentView()
    }
}

Home - 主页

思路

  1. 先做出一个蒙版
  2. 做一个区域的图片
    在这里插入图片描述
  1. 初始化传感器 - 传递偏移的值,进行传感器的设置,进行高光部分偏移
//
//  Home.swift
//  MotionParallax (iOS)
//
//  Created by lyh on 2022/8/31.
//

import SwiftUI

struct Home: View {
    
    
    
    @StateObject var motionData = MotionObserver()
     
    
    var body: some View {
    
    
        ZStack{
    
    
            GeometryReader{
    
    proxy in
                let size = proxy.size
                Image("BG")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: size.width, height: size.height)
                    .cornerRadius(0)
                
                // Slighly Dimming...
                // 丝滑调光...
                Color.black
                    .opacity(0.2)
                
            }
            // Blur Overlay...
            // 模糊覆盖……
            .overlay(.ultraThinMaterial)
            .ignoresSafeArea()
            
            
            GeometryReader{
    
    proxy in
                let size = proxy.size
                Image("BG")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                // if you want only frame moving just apply negative in offset here...
                // 如果你只想让帧移动只需在这里设置负偏移。
                // 这里是整张有光背景移动连同图片
//                    .offset(motionData.movingOffset)
                // 这个是控制有光的背景进行移动
                    .offset(x:-motionData.movingOffset.width,y:-motionData.movingOffset.height)
                    .frame(width: size.width * 2, height: size.height * 2)
                // Applying Offset to image to get nice Parallax...
                // //应用偏移到图像获得不错的视差…
                    .frame(width: size.width, height: size.height)
                

            }
            .frame(height:450)
            .cornerRadius(25)
            .padding(.horizontal,40)
            // Applying offset here...
            // to look like its moving on real time motion data...
            //在这里应用偏移…
            //看起来像它在实时运动数据上移动…
            offset(motionData.movingOffset)
            

        }
        // Calling Motion Updater with duration
        .onAppear(perform: {
    
    
            // duration = how much you need to move the view in both sides...
            // since we have padded 40 on each side
            // so we can use 30...
            // duration =你需要在视图两边移动多少…
            //因为我们每边填充了40
            //这样我们就可以使用30…
            motionData.fetchMotionData(duration: 50)
        })
        // Preffered to be Dark
        // 黑暗
        .environment(\.colorScheme, .dark)
    }
    
    
}

struct Home_Previews: PreviewProvider {
    
    
    static var previews: some View {
    
    
        Home()
    }
}

MotionObserver - 传感器监听

//
//  MotionObserver.swift
//  MotionParallax (iOS)
//
//  Created by lyh on 2022/8/31.
//

import SwiftUI
// Improting Core Motion...
// 进口核心运动……
import CoreMotion

class MotionObserver: ObservableObject {
    
    
    // Motion Manager...
    // 运动经理……
    @Published var motionManager = CMMotionManager()
    
    
    // Storing Motion Data to animate view in parallax...
    // Note....
    // roll -> X-Axis
    // pitch -> Y-Axis...
    //存储运动数据动画视差视图…
    //注意……
    //转→轴
    //螺距→轴……
    @Published var xValue : CGFloat = 0
    @Published var yValue : CGFloat = 0

    // Moving Offset
    // 移动抵消
    @Published var movingOffset : CGSize = .zero

//    init() {
    
    
//        fetchMotionData()
//    }
    
    func fetchMotionData(duration:CGFloat){
    
    
        // Calling Motion updates handler...
        //调用动态更新处理程序…

        motionManager.startDeviceMotionUpdates(to: .main) {
    
     data, err in
            
            if let error = err {
    
    
                print(error.localizedDescription)
                return
            }
            guard let data = data else {
    
    
                print("ERROR IN DATA")
                return
            }
            print(data.attitude)
            
            // Animation Using Time Curve...
            // Rough values for nice Aniamtions....
            // 动画使用时间曲线…
            // 为漂亮的动画粗略的值
            withAnimation(.timingCurve(0.18, 0.78, 0.18, 1,duration: 0.77)) {
    
    
                self.xValue = data.attitude.roll
                self.yValue = data.attitude.pitch
                self.movingOffset = self.getOffset(duration: duration)
            }
        }
    }
    
    func getOffset(duration: CGFloat) -> CGSize {
    
    
        var width = xValue * duration
        var height = yValue * duration
        
        
        width = (width < 0 ? (-width > duration ? -duration: width) : (width > duration ? duration: width))
        height = (height < 0 ? (-height > duration ? -duration: height) : (height > duration ? duration: height))

        // avoiding if view goes over duration ...
        // 避免如果视图超过持续时间…

        
        return CGSize(width: width, height: height)

    }
}


猜你喜欢

转载自blog.csdn.net/qq_42816425/article/details/126614515