此项目是 适用于 iOS 的 SAP Fiori 设计指南中增强现实 (AR) 模式的 SwiftUI 实现。
当前支持
您必须配置技术用户和密码才能解析包!
该软件包旨在通过 Swift Package Manager 使用。 要将该软件包添加到您的应用程序目标,请导航至 File > Add Packages... >,然后添加存储库 URL。
您可以选择以下软件包产品之一添加到您的应用程序/框架目标。
软件包产品 | 何时使用 |
---|---|
FioriAR | 您尚未嵌入来自 SAP BTP SDK for iOS 的二进制框架 |
FioriAR-requiresToEmbedXCFrameworks | 您已将 SAPCommon 和 SAPFoundation 二进制框架嵌入到您的目标中 |
FioriAR 2.0 与之前的版本不完全兼容。 但是,迁移并不困难。 当您准备升级项目中的 FioriAR 时,请遵循迁移指南。
AR 注释是指与真实世界中图像或对象相关的 标记相匹配的卡片。 要在世界视图中查看注释,用户使用 AR 扫描仪扫描图像/对象。
不需要 3D 建模来表示 AR 注释,因为相应的控件(ARScanView
、MarkerView
和 CardView
)已在此软件包中使用 SwiftUI 实现。
应用程序开发人员需要提供一个相对于 Image
或 Object
锚点的标记场景。 这种场景创建是可能的
根据场景的存储位置和方式(.rcproject
、.reality
、.usdz
文件或 SAP Mobile Services),应用程序开发人员必须指定适当的加载策略来填充场景和相关的卡片数据。
卡片和标记支持 SwiftUI ViewBuilder 以允许自定义设计。
FioriAR 提供了可重用的视图和实用程序,可直接从您的应用程序创建/更新/删除带有 AR 注释的场景。 考虑到创建和处理 AR 注释的容易程度,这是推荐的方法。
场景信息将远程存储在 SAP Mobile Services 中。 作为先决条件,需要将功能 Mobile Augmented Reality 分配给 SAP Mobile Services cockpit 中的应用程序。
SAP Mobile Services 允许管理员 编辑增强现实场景,这有助于维护多种语言的 AR 注释文本。
呈现 SceneAuthoringView
将提供一个用户界面,您的用户可以在其中创建 AR 注释,并指定它们相对于图像锚点的位置。
import FioriAR
import SAPFoundation
struct ARCardAuthoringContentView: View {
public var serverUrl: URL
public var sapURLSession: SAPURLSession
public var sceneId: Int? // nil in case of you want to create a new scene
var body: some View {
SceneAuthoringView(title: "Annotations",
serviceURL: serverUrl,
sapURLSession: sapURLSession,
sceneIdentifier: SceneIdentifyingAttribute.id(sceneId))
.onSceneEdit { sceneEdit in
switch sceneEdit {
case .created(card: let card):
print("Card locally created: \(card.title_)")
case .updated(card: let card):
print("Card locally updated: \(card.title_)")
case .deleted(card: let card):
print("Card locally deleted: \(card.title_)")
case .published(sceneID: let sceneID):
print("Scene \(sceneID) created/updated")
}
}
}
}
使用 ServiceStrategy
从 SAP Mobile Services 获取场景信息,并在 AR 世界中使用 ARAnnotationsView
呈现其 AR 注释。
struct ARCardsServiceView: View {
@StateObject var arModel = ARAnnotationViewModel<CodableCardItem>()
@StateObject var asyncStrategy = ServiceStrategy<CodableCardItem>!
init(serverURL: URL, sapURLSession: SAPURLSession, sceneId: Int) {
_asyncStrategy = ServiceStrategy<CodableCardItem>(
serviceURL: serviceURL,
sapURLSession: sapURLSession,
sceneIdentifier: SceneIdentifyingAttribute.id(sceneId)
)
}
var body: some View {
ARAnnotationsView(arModel: arModel,
cardAction: { id in
print("Action for card \(id) was triggered")
})
.onAppear(perform: loadInitialData)
}
func loadInitialData() {
do {
try self.arModel.loadAsync(loadingStrategy: self.asyncStrategy)
} catch {
print(error)
}
}
}
FioriAR 可以处理使用 Apple 的 Reality Composer 创建的 AR 体验,但 AR 注释的处理更加复杂,因为
CardItemModel
id.usdz
文件(在首选项或 iOS 应用程序设置中启用 usdz 导出).reality
文件或.rcproject
注意:
此 Swift 软件包提供了各种加载策略,具体取决于您用于导出场景的文件格式。
加载策略接受元素数组,每个元素都符合 CardItemModel
协议,以填充卡片相关数据。 模型的 *id* 属性必须对应于 Reality Composer 中实体(球体)的 *name*。
每个加载策略还有一个初始化器,用于接受由 JSON 数组表示的 Data
。
// JSON key/value:
"id": String,
"title_": String,
"subtitle_": String?,
"detailImage_": Data?, // base64 encoding of Image
"actionText_": String?,
"icon_": String? // systemName of SFSymbol
除了场景和卡片相关数据之外,支持的加载策略(UsdzFileStrategy
、RealityFileStrategy
和 RCProjectStrategy
)还需要有关用于检测场景的锚点的信息。 使用 Image
锚点需要应用程序开发人员提供 anchorImage 及其 physicalWidth 作为初始化器参数。 对于 Object
锚点,anchorImage 和 physicalWidth 参数可以为 nil。
场景可以用不同的文件类型表示,并且每个策略都需要不同的数据和设置。
.usdz
文件的 URL 路径.reality
文件的 URL 路径和场景的名称.rcproject
文件的名称和场景的名称注意:
.rcproject
文件是应用程序包的一部分,以便该文件在构建时已经可用。 将该文件拖到 Xcode 中即可。用法示例:创建 ContentView 并加载数据
import FioriAR
struct FioriARKCardsExample: View {
@StateObject var arModel = ARAnnotationViewModel<CodableCardItem>()
var body: some View {
/**
Initializes an AR Experience with a Scanning View flow with Markers and Cards upon anchor discovery
- Parameters:
- arModel: The View Model which handles the logic for the AR Experience
- guideImage: image to display for anchor detection in the Scanning View, if nil then the image anchor will be used by default
- cardAction: Card Action
*/
ARAnnotationsView(arModel: arModel, guideImage: Image("qrImage"), cardAction: { id in
// action to pass to corresponding card from the CardItemModel id
})
.onAppear(perform: loadInitialData)
}
// Example to use a `UsdzFileStrategy` to populate scene related information (stored in a .usdz file which could have been fetched from a remote server during runtime) as well as card-related information (stored in a .json file which could have been fetched from a remote server as well)
func loadInitialData() {
let usdzFilePath = FileManager.default.getDocumentsDirectory().appendingPathComponent(FileManager.usdzFiles).appendingPathComponent("ExampleRC.usdz")
guard let anchorImage = UIImage(named: "qrImage"),
let jsonUrl = Bundle.main.url(forResource: "Tests", withExtension: "json") else { return }
do {
let jsonData = try Data(contentsOf: jsonUrl)
let strategy = try UsdzFileStrategy(jsonData: jsonData, anchorImage: anchorImage, physicalWidth: 0.1, usdzFilePath: usdzFilePath)
arModel.load(loadingStrategy: strategy)
} catch {
print(error)
}
}
}
创建 GitHub issue 以创建错误报告、提交功能请求或提问。
如果您想贡献代码,请查看贡献指南
可以使用此软件包中已有的演示应用程序进一步探索功能 (Apps/Examples/Examples.xcodeproj
)。 有关更多信息,请参阅其 README。