WeAre - AR相册

ARKit

线上地址 https://itunes.apple.com/cn/app/weare/id1304227680?mt=8

开源地址 https://github.com/SherlockQi/HeavenMemoirs 欢迎(跪求)Star!

WeAre

技术点

AR初始化 在新建项目时可以直接创建 AR 项目, xcode 会创造一个 AR 项目的模板.

也可以创建普通的项目,在需要实现 AR 功能的控制器中实现如下代码进行初始化.

      import ARKitlet sceneView = ARSCNView()override func viewDidLoad() {super.viewDidLoad()sceneView.frame = view.boundsview.addSubview(sceneView)sceneView.delegate = selfsceneView.showsStatistics = true// 创建一个场景,系统默认是没有的let scene = SCNScene()sceneView.scene = scene//不允许用户操作摄像机sceneView.allowsCameraControl = false//抗锯齿sceneView.antialiasingMode = .multisampling4X}override func viewWillAppear(_ animated: Bool) {super.viewWillAppear(animated)let configuration = ARWorldTrackingConfiguration()sceneView.session.run(configuration)}override func viewWillDisappear(_ animated: Bool) {super.viewWillDisappear(animated)sceneView.session.pause()}
复制代码

添加节点

      //我使用的是 SCNPlane 来充当相框,也可以使用"厚度"很小的 SCNBoxlet photo = SCNPlane(width: 1, height: 1)//photo.cornerRadius = 0.01let image = UIImage(named: "0")//纹路可以使图片,也可以是颜色photo.firstMaterial?.diffuse.contents = image//photo.firstMaterial?.diffuse.contents = UIColor.redlet photoNode = SCNNode(geometry: photo)//节点的位置let vector3 = SCNVector3Make(-1, -1, -1) photoNode.position = vector3sceneView.scene.rootNode.addChildNode(photoNode)
复制代码
      let text = SCNText(string: "文字", extrusionDepth: 0.1)text.font = UIFont.systemFont(ofSize: 0.4)let textNode = SCNNode(geometry: text)textNode.position = SCNVector3Make(0,0, -1)//文字的图片/颜色text.firstMaterial?.diffuse.contents = UIImage(named: color)sceneView.scene.rootNode.addChildNode(textNode)
复制代码
可供选择的几何图形SCNText 文字  SCNPlane 平面  SCNBox 盒子  SCNPyramid 锥形  SCNSphere 球  SCNCylinder 圆柱  SCNCone 圆锥  SCNTube 圆筒  SCNCapsule 胶囊  SCNTorus 圆环  SCNFloor 地板  SCNShape 自定义
复制代码

全景图实现

      想象自己站在一个球的球心处,球的内表面涂着壁画,那么是不是就实现了全景图.所以用一个Sphere 节点包裹着相机节点(也就是0位置节点),再设置Sphere节点的内表面纹理,就实现了功能.let sphere = SCNSphere(radius: 15)let sphereNode = SCNNode(geometry: sphere)sphere.firstMaterial?.isDoubleSided = truesphere.firstMaterial?.diffuse.contents = imagesphereNode.position = SCNVector3Zeroscene.rootNode.addChildNode(sphereNode)
复制代码

播放视频

      let height:CGFloat = CGFloat(width) * videoSize.height/videoSize.widthlet box = SCNBox(width: width, height: height, length: 0.3, chamferRadius: 0)boxNode.geometry = box;boxNode.geometry?.firstMaterial?.isDoubleSided = trueboxNode.position = SCNVector3Make(0, 0, -5);box.firstMaterial?.diffuse.contents = UIColor.redself.scene.rootNode.addChildNode(boxNode);let avplayer = AVPlayer(url: url)avplayer.volume = rescoucceConfiguration.video_isSilence ? 0.0 : 3.0videoPlayer = avplayerlet videoNode = SKVideoNode(avPlayer: avplayer)NotificationCenter.default.addObserver(self, selector: #selector(playEnd(notify:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)videoNode.size = CGSize(width: 1600, height: 900)videoNode.position = CGPoint(x: videoNode.size.width/2, y: videoNode.size.height/2)videoNode.zRotation = CGFloat(Float.pi)let skScene = SKScene()skScene.addChild(videoNode)skScene.size = videoNode.sizebox.firstMaterial?.diffuse.contents = skScenevideoNode.play()
复制代码

粒子效果

      /*particleName = "bokeh.scnp"particleName = "rain.scnp"particleName = "confetti.scnp"**/particleSytem = SCNParticleSystem(named: particleName, inDirectory: nil){particleNode.addParticleSystem(particleSytem)particleNode.position = SCNVector3Make(0, Y, 0)self.scene.rootNode.addChildNode(particleNode)
复制代码

节点点击事件

      //给 场景视图sceneView 添加点击事件let tap = UITapGestureRecognizer(target: self, action: #selector(tapHandle(gesture:)))sceneView.addGestureRecognizer(tap)
复制代码
  @objc func tapHandle(gesture:UITapGestureRecognizer){let results:[SCNHitTestResult] = (self.sceneView?.hitTest(gesture.location(ofTouch: 0, in: self.sceneView), options: nil))!guard let firstNode  = results.first else{return}// 这就是点击到的节点 可以对他做一些事情 或者根据这个节点的某些属性执行不同的方法let node = firstNode.node.copy() as! SCNNodeif firstNode.node == self.selectNode {...推远照片...}else{...拉近照片...selectNode = node}
}
复制代码

节点动画 我的另一篇文章中有详细记录ARKit-动画 //拉近(推远)照片

      //这只是其中一种方法let newPosition  = SCNVector3Make(firstNode.node.worldPosition.x*2, firstNode.node.worldPosition.y*2, firstNode.node.worldPosition.z*2)let comeOut = SCNAction.move(to: newPosition, duration: 1.2)firstNode.node.runAction(comeOut)
复制代码

自传/公转

      //自转let box = SCNBox(width: boxW, height: boxW, length: boxW, chamferRadius: 0)let boxNode = SCNNode(geometry: box)boxNode.position = vector3let emptyNode = SCNNode()emptyNode.position = SCNVector3ZeroemptyNode.rotation = SCNVector4Make(0, 1, 0, Float.pi/Float(L/2) * Float(index))emptyNode.addChildNode(boxNode)photoRingNode.addChildNode(emptyNode)let ringAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: right, z: 0, duration: 2))boxNode.runAction(ringAction)//公转 把节点加到一个正在自传的节点上就可以了
复制代码

录屏 录屏是使用ReplayKit完成的 开始录屏

      协议      RPScreenRecorderDelegate,RPPreviewViewControllerDelegateRPScreenRecorder.shared().startRecording(handler: nil)RPScreenRecorder.shared().delegate = self
复制代码

录制代理

func screenRecorder(_ screenRecorder: RPScreenRecorder, didStopRecordingWith previewViewController: RPPreviewViewController?, error: Error?) {print(error ?? "error")if error != nil{print("error:", error ?? "")DispatchQueue.main.async {let string = error?.localizedDescriptionITTPromptView .showMessage(string, andFrameY: 0)print(string ?? "")//录制期间失败self.showFailReplay()}}else{print("else")}print("start recording handler")}//录制失败func showFailReplay(){let sb = UIStoryboard(name: "Main", bundle: nil)let vc = sb.instantiateViewController(withIdentifier: "HKExplainViewController")self.navigationController?.pushViewController(vc, animated: true)self.replayButtonRight.constant = 85;for button in self.smailButtons {button.alpha = 1}self.mainButton.alpha = 1UIView.animate(withDuration: 2.5) {self.stopReplayButton.alpha = 0self.view.layoutIfNeeded()}}
复制代码

结束并弹出预览控制器

      RPScreenRecorder.shared().stopRecording { (vc, erroe) invc?.previewControllerDelegate = selfvc?.title = "We Are"self.present(vc!, animated: true, completion: nil)}
复制代码

预览控制器的代理

    func previewController(_ previewController: RPPreviewViewController, didFinishWithActivityTypes activityTypes: Set<String>) {print(activityTypes)//取消if activityTypes.count == 0 {previewController.dismiss(animated: true, completion: nil)}//保存if activityTypes.contains("com.apple.UIKit.activity.SaveToCameraRoll"){ITTPromptView .showMessage("视频已保存在相册", andFrameY: 0)previewController.dismiss(animated: true, completion: nil)//检测到您刚刚保存了视频 是否想要分享let delay = DispatchTime.now() + .seconds(2)DispatchQueue.main.asyncAfter(deadline: delay) {self.outputVideo()}}}
复制代码

欢迎(跪求)Star!

开源一个线上项目 WeAre-AR相册相关推荐

  1. 线上项目开源 -- WeAre(AR 相册)

    线上地址 https://itunes.apple.com/cn/app/weare/id1304227680?mt=8 开源地址 https://github.com/SherlockQi/Heav ...

  2. iOS宇宙大战游戏、调试工具、各种动画、AR相册、相机图片编辑等源码

    iOS精选源码 日期时间选择器,swift Space Battle 宇宙大战 SpriteKit游戏源码 LLDebugTool - 便捷的IOS调试工具(新增截屏功能) 相机扫描or长按识别二维码 ...

  3. Flutter 小技巧之实现一个精美的动画相册效果

    今天的小技巧主要是「抄袭」一个充满设计感的相册控件,如下图所示是 gskinner 开源应用 wonderous 里一个相片集的实现效果,可以看到相册支持上下左右滑动,并带有高亮展示的动画效果,而且相 ...

  4. 【Unity】创建一个自己的AR脸部特效安卓程序

    目录 1 创建一个换脸AR场景 2 下载官方提供的BasicFaceFilterAssets资源 3 设置AR面部追踪 4 配置AR Face Manager 5 配置AR Camera为前置摄像头 ...

  5. 开源一个友盟 for android 操作的封装包

    开源一个友盟 for android 操作的封装包 介绍 详解 介绍 这个库,把友盟的初始化设置,自定义事件,还有使用时长进行了一层简单的封装,例如,初始化设置 UmengOption option ...

  6. 【Unity】创建一个自己的AR安卓程序

    目录 1 环境配置 2 下载官方提供的AR Starter工程 3 AR Starter工程中的包以及打包设置 3.1 Package Manager 3.2 Player Settings 4 创建 ...

  7. 开源一个微信+wap的建站系统

    开源一个微信+wap的建站系统 首先介绍一下此系统的几个重要功能: 1:完善的客服分流系统(对接阿里云旺),可实现手机端+网站端的客服即时通讯系统 2:独立的供货商系统(暂时不是很完善,没有独立出供货 ...

  8. [vue]开源一个精致完整的Vue项目(豆瓣)

    各位道友,开源一个Vue2+项目: Awesome douban DEMO created with Vue2.x + Vuex + Vue-router + vue-resource 项目地址: h ...

  9. 开源一个微信小程序,支持蓝牙配网+WiFi双控制ESP32-C3应用示范;(附带Demo)

    文章目录 一.前言 二. Blufi乐鑫自研的蓝牙配网协议 ESP32 配网流程 流程图 三.相关代码 3.1 蓝牙快速配网 3.2 蓝牙本地控制 2.3 外设驱动 3.1 蓝牙搜索 3.2 蓝牙服务 ...

最新文章

  1. 关于Mongodb索引创建的一些体会
  2. python简单代码input-【python系统学习05】input函数——实现人机交互
  3. android arrays.xml 二维数组,android中怎的从xml文件中解析一个二维数组
  4. ActionTileViewController.js
  5. Eigen入门之密集矩阵 9 - 别名混乱Aliasing
  6. 关于eclipse中文注释乱码的问题
  7. HTML+CSS+JS实现 ❤️酷炫情人节爱心动画特效❤️
  8. wifidog java_wifidog 配置中文说明
  9. 目标检测之YOLO V2 V3
  10. C#设计模式之1-工厂方法模式
  11. 6.1 文件对象常用方法与属性
  12. C# 读取Excel CSV 类型文件到DataSet中,反之从DataSet写入excel
  13. KM算法(最优匹配)
  14. 24. Element namespaceURI 属性
  15. 激光导航AGV为何如此受企业青睐?
  16. Zynq FPGA低时延H.264设计方案(编码+解码< 1ms)
  17. cropper:图片裁剪工具
  18. 关于谭浩强老先生的《C++程序设计教程》 1
  19. 【Android】使用阿里云直播实现手机直播功能
  20. 技术与思维,哪个更重要?

热门文章

  1. 正则表达式限制文本框输入内容
  2. 你客户的名片现在怎么处理?看看微信营销是怎么做的?
  3. 黑马程序员--银行调度系统
  4. 机器学习可以分为哪几类?机器学习分类
  5. POSITION 类型
  6. 第 19 节 委托详解
  7. 2018android手机机皇,2018年安卓机皇推荐,这几款是真的不错
  8. mysql唯一索引和联合索引的区别_mysql中,索引,主键,唯一索引,联合索引的区别...
  9. 不封号PC微信协议|微信iPad协议稳定|企业微信Api,群发多发,私有化部署解决方案、企业微信协议
  10. mysql inner join_MySQL JOIN 语法说明与 INNER JOIN 语法用法实例