[
](marklucking.medium.com/?source=pos…)
6月14日
-
5分钟阅读
[
保存
用 SwiftUI 在 SceneKit 中构建 3D 条形图
插入 SwiftUI 图表库的缺失组件

这篇文章中你将构建的图表的GIF动画
我是在2022年WWDC大会之前开始写这篇文章的,这次大会上苹果宣布了一个性感的新框架--Charts。当我在最新的SwiftUI讲座中听到这个消息时,我曾短暂地担心自己可能被打入冷宫,但当我意识到苹果的图表框架只做2D图表时,我感觉好多了。
也就是说,去年我确实写了几篇关于构建二维饼图的文章,现在这些文章都已经确定死亡了--但这篇文章还活着。在本文中,请和我一起使用我在过去一个多月里一直在谈论的SceneKit框架,不是为了构建一个游戏,而是一个更平凡的东西,一个3D柱状图。
技术栈
好的--我们将需要一个在SwiftUI中运行的SCNScene ,并有一个连接两者的Combine publisher。在这个场景中,我想画一条方框和标签,方框我打算用SCNMorph ,以便随着时间的推移改变大小。我将使用与苹果公司关于新图表框架的演讲中所描述的结构类似的结构使其运行。
一个三维图表
邦--我首先将这些线条添加到我的场景中。它们不加载任何数据;它们只是凭空产生一些数字,并用线条创建一个超级简单的三维条形图。这里的第一个挑战是,形状从它们的中心生长,这种状态似乎几乎不可能改变。
有效的代码为我们建立了一个漂亮的简单的4D图表,看起来像这样。
3D柱状图的快照[包括一个楼层,接下来会提到]
动画技术
SCNMorph 在画好它并排好条形图后,我决定添加一个SCNFloor ,使它看起来更时髦一些,并在一个SCNTransation ,用动画改变条形图的大小。

一个SCNTransaction管理我们的3D图表的大小调整
定位
我通过Combine框架将其链接到SwiftUI界面,使用了我在本文 中部分概述的订阅技术,并使用了一个带有SceneDelegate的单子类。
上面的代码包含在GameScene.swift 文件中,基于Combine的相关主题通过SwiftUI界面中的一个简单的Text对象触发了。
Text("_5yawC") .onTapGesture { relocating.send(._5yawClockwise)}
代码可以让我在屏幕上定位我的3D条形图,以获得最佳的观看效果。
相机视图
正如我在本文中指出的那样,仅仅移动对象是不够的,我实现了一个单独的机制来移动场景用于观察3D柱状图的摄像头。这一次我在SceneDelegate.swift
Common.shared 是对SwiftUI接口和你在这里看到的SceneKitDelegate代码之间的共享结构的简单引用。
改变superSIMDValue.xV 的值会导致不连续的移动,改变share.superSIMDValue.RX 的值会导致连续的移动,定时执行,每spawnTime 秒。
颜色调色板
当然,柱状图需要颜色,这个主题比你想象的要多。我在这里写了关于颜色的所有内容。直接说吧,我决定现在添加一个固定的12种颜色的调色板。
文本标签
正如WWDC 2022关于这个主题的演讲会告诉你,没有标签的图表不是很有用,所以我也添加了一些标签。

带有显示不同数值的标签的3D条形图
注意,我使用这段代码倾斜了文本,以确保其可读性,然后再将其添加到显示的条形图中。
let quaternion = simd_quatf(angle: GLKMathDegreesToRadians(-45), axis: simd_float3(1,0,0))textNodes[k].simdOrientation = quaternion * textNodes[k].simdOrientationsourceNodes[k].addChildNode(textNodes[k])
排序
在这个项目中,我没有意识到的一件事是,三维条形图只有在描述一个随着时间推移而变大的数据集,即一个排序的数据集时才会好看。我在视觉上做到了这一点;因为这当然是乐趣的一半。

三维柱状图的自我分类。
图例
最后,我在SceneKit 视图的顶部添加了一个 SwiftUI 图例,这就是净结果。
我认为3D柱状图是非常合理的;你怎么看。在这里,我也应该对这篇关于颜色的文章点个头。我使用了这篇文章中描述的调色板。
未来
我认为,你可以做几件事来使它变得更好。
- 排序本身可以更加动态,在你改变条形图的值时发生。
- 我认为标签在条形图顶部的位置可以做得更好--进行一些微调。
- 数据可以/应该被动态加载,也许是JSON或XML源。
- 你可以用摄像机做更多的事情,使用一些预先设定的路线,比如绕着图表转或者飞过它。
所有这一切让我想到了这篇文章的结尾,我希望你能像我写这篇文章一样喜欢阅读它。你可以在这个链接上找到一个包含所有代码的bitbucket。