Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >手把手教你从 Core Data 迁移到 Realm - 简书

手把手教你从 Core Data 迁移到 Realm - 简书

作者头像
一缕殇流化隐半边冰霜
发布于 2024-02-14 01:44:16
发布于 2024-02-14 01:44:16
27500
代码可运行
举报
文章被收录于专栏:冰霜之地冰霜之地
运行总次数:0
代码可运行
前言

看了这篇文章的标题,也许有些人还不知道Realm是什么,那么我先简单介绍一下这个新生的数据库。号称是用来替代SQLite 和 Core Data的。Realm有以下优点:

  1. 使用方便 Realm并不是基于SQLite的对象关系映射数据库。它是使用自己的持久化引擎,为简单和速度而生。用户们说,他们在数分钟之内就上手了Realm,构建一个app只需要数小时,每个app开发时间至少节约数周的时间。
  2. 快 Realm比其他的对象关系映射型数据库(Object Relational Mapping),甚至比原生的SQLite更加快,这都得益于它零拷贝的设计。看看iOS用户和Android用户都是怎么评价它的快的 Twitter
  3. 跨平台 Realm 支持 iOS 和 OS X (Objective‑C & Swift) 和Android。你可以通过使用相同的model,共享Realm文件到各个平台,JavaSwiftObjective-C。并且在全平台可以使用相同的业务逻辑
  4. 优秀的特性 Realm支持先进的特性,如加密图形查询轻松的迁移。Realm的API是一个非常适合打造高响应的应用程​​序,并且Realm为我们提供方便的组件,以轻松构建复杂的用户界面
  5. 值得信任 Realm已经获得了银行,医疗保健提供商,复杂的企业app,星巴克这些产品的青睐。
  6. 社区驱动 Realm是Github上星标最多的数据库里面排名第四,仅次于Java 和 Cocoa 的repos。除了核心工程之外,Realm的社区已经编译了上百个app插件和组件
  7. 支持 可以从Realm公司快速获得官方的答案,去编译和支持你的数据库。Realm的团队会在Github, StackOverflow, & Twitter回答大家的各种问题

下面再发3张令人惊喜的性能对比图

上图是每秒能在20万条数据中进行查询后count的次数。realm每秒可以进行30.9次查询后count。SQLite仅仅只有每秒13.6次查询后的count,相对于Core Data只有可怜的1。

在20万条中进行一次遍历查询,数据和前面的count相似:Realm一秒可以遍历20万条数据31次,而RCore Data只能进行两次查询。 SQLite也只有14次而已。

这是在一次事务每秒插入数据的对比,Realm每秒可以插入9.4万条记录,在这个比较里纯SQLite的性能最好,每秒可以插入17.8万条记录。然而封装了SQLite的FMDB的成绩大概是Realm的一半,4.7万,Core Data就更低了,只有可怜的1.8万。

从以上3张图可以看出Realm优秀的特性。那么我们开始使用Realm吧。第一步就是把本地的数据库换成Realm。

下面是我翻译的一篇手把手教程,那么让我们赶紧通过教程,来把Core Data迁移到Realm吧。

原文
译文

把一个使用core data框架作为数据库存储方式的app,迁移到Realm的确是一件很容易的事情。如果你现在有一个已经用了Core Data的app,并且考虑换成Realm,这个手把手教程正适合你!

很多开发者在用户界面,高度集成了Core Data(有时可能有上千行代码),这时很多人会告诉你转换Core Data到Realm可能会花数小时。Core Data和Realm两者都是把你的数据当成Object看待,所以迁移通常是很直接的过程:把你已经存在的Core Data的代码重构成使用Realm API的过程是很简单的。

迁移后,你会为Realm为你app带来的易用性,速度快,和稳定性而感到兴奋。

1.移除Core Data Framework

首先,如果你的app当前正在使用Core Data,你需要找出哪些代码是包含了Core Data的代码。这些代码是需要重构的。幸运的是,这里有一个手动的方式去做这件事:你可以手动的在整个代码里面搜索相关的代码,然后删除每个导入了Core Data头文件声明的语句

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import <CoreData/CoreData.h>
//or
@import CoreData;

一旦这样删除以后,每一行使用了Core Data的将会报一个编译错误,接下来,解决这些编译错误只是时间问题。

2.移除Core Data的设置代码

在Core Data中,对model objects的更改是要通过managed object context object来实现的。而managed object context objects又是被persistent store coordinator object创建的,它们两者又是被managed object model object创建的。

可以这么说,在你开始思考用Core Data读取,或者写入数据的时候,你通常需要在你的app中的某处去设置依赖的对象,暴露一些Core Data的方法给你的app逻辑使用。无论在你的application delegate中,全局的单例中,或者就是在inline实现中,这些地方都会存在大量的潜在的Core Data 设置代码。

当你准备转换到Realm时,所有的这些代码都可以删掉。

在Realm中,所有设置都在你第一次创建一个Realm object的时候就已经都完成了。当然也是可以手动去配置它,就像你指定Realm数据文件存储在你的硬盘的哪个路径下,这些完全都可以在runtime的时候去选择的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
RLMRealm *defaultRealm = [RLMRealm defaultRealm];
//or
let realm = Realm()

感觉很好吧?

3.迁移model文件

在Core Data中,实用的那些类都是被定义成NSManagedObject的子类。这些object的接口都是很标准的,原始的类型(比如NSInteger 和 CGFloat)是不能被使用的,它们必须抽象成一个NSNumber对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface Dog : NSManagedObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, strong) NSDate *birthdate;

@end

@implementation Dog

@dynamic name;
@dynamic age;
@dynamic birthdate;

@end

把这些managed object subclasses转换成Realm是非常简单的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface Dog : RLMObject

@property NSString *uuid;
@property NSString *name;
@property NSInteger age;
@property NSDate *birthdate;

@end

@implementation Dog

+ (NSString *)primaryKey
{
    return @"uuid";
}

+ (NSDictionary *)defaultPropertyValues
{
    return @{ @"uuid" : [[NSUUID UUID] UUIDString],
              @"name" : @"",
              @"birthdate" : [NSDate date]};
}

@end

或者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Dog: Object {
    dynamic var uuid = NSUUID().UUIDString
    dynamic var name = ""
    dynamic var age = 0
    dynamic var birthdate = NSDate().date
    
    override static func primaryKey() -> String? {
        return "uuid"
    }
}

完成!这是多么的简单?

看这些实现,还是有一些Realm的细节需要注意的。

对于初次使用Realm的人来说,没有必要去指定属性关键字,Realm在内部已经管理了。所以这些类的头文件看上去都很精简。此外,Realm支持简单的数据类型,比如NSInteger 和 CGFloat,所有所有的NSNumber都可以安全的删除。

另一方面,这有一些关于Realm model的声明额外的说明。

  1. Core Data objects通过内部的NSManagedObjectID属性去唯一标识一个objects,Realm把这个留给开发者去完成。在上面的例子中,我们额外添加了一个名为uuid的属性,然后通过调用 [RLMObject primaryKey]方法去作为这个class的唯一标识。当然,如果你的objects完全不需要唯一标识,这些都可以跳过。
  2. 在写数据的过程中(这个过程不会太长!),Realm不能处理nil的object的属性。原因是,在[RLMObject defaultPropertyValues]这个类方法中给每个object在最初创建的时候,每个object属性都定义了一系列default值。当然这只是暂时的,我们很高兴的告诉你,在接下来的更新中,我们将会支持Realm object的属性可以为nil。
4.迁移写操作

如果你不能保存你的数据,这肯定不是一个持久的方案!创建一个新的Core Data对象然后再简单的修改一下它,需要下面这些代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Create a new Dog
Dog *newDog = [NSEntityDescription insertNewObjectForEntityForName:@"Dog" inManagedObjectContext:myContext];
newDog.name = @"McGruff";

//Save the new Dog object to disk
NSError *saveError = nil;
[newDog.managedObjectContext save:&saveError];

//Rename the Dog
newDog.name = @"Pluto";
[newDog.managedObjectContext save:&saveError];

相比之下,Realm保存的操作是略有不同的,但在相同的范围内修改上面的代码,仍然有相似的地方。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Create the dog object
Dog *newDog = [[Dog alloc] init];
newDog.name = @"McGruff";

//Save the new Dog object to disk (Using a block for the transaction)
RLMRealm *defaultRealm = [RLMRealm defaultRealm];
[defaultRealm transactionWithBlock:^{
    [defaultRealm addObject:newDog];
}];

//Rename the dog (Using open/close methods for the transaction)
[defaultRealm beginWriteTransaction];
newDog.name = @"Pluto";
[defaultRealm commitWriteTransaction];

或者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Create the dog object
let mydog = Dog()
myDog.name = "McGruff"

//Save the new Dog object to disk (Using a block for the transaction)
Realm().write {
    realm.add(myDog)
}

//Rename the dog (Using open/close methods for the transaction)
Realm().beginWrite()
myDog.name = "Pluto"
Realm().commitWrite()

完成!我们的数据被保存了!

明显的不同是,在Realm中,一旦一个objects被添加到一个Realm object中,它就是不可被修改的。为了在修改属性操作的后面执行,Realm object会被保存在一个写的事务中。这种不能被修改的model,保证了在不同线程中读/写 object数据的情况下,数据的一致性。

Core Data的实现确实可以改变属性,然后调用save方法,对比Realm的实现,只是一些小小的不同罢了。

5.迁移查询

另一方面,如果你不能检索查询你的数据,这肯定不是一个持久的方案!

在Core Data的基础实现中,它运用了fetch requests的概念去从硬盘检索数据。一个fetch request object是被当成一个单独的实例化对象去创建的,包含了一些额外的过滤参数,排序条件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NSManagedObjectContext *context = self.managedObjectContext;

//A fetch request to get all dogs younger than 5 years old, in alphabetical order
NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"Dog" inManagedObjectContext:context];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 5"];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;
request.predicate = predicate;
request.sortDescriptors = @[sortDescriptor];

NSError *error;
NSArray *dogs = [moc executeFetchRequest:request error:&error];

虽然这确实挺好,但是需要编写大量的代码!一些聪明的开发者就开发了一些library使这些代码编写的更加容易。比如MagicalRecord。

对比这些,使用了Realm之后,这些查询的等效代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
RLMResults *dogs = [[Dog objectsWhere:@"age < 5"] sortedResultsUsingProperty:@"name" ascending:YES];

或者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var dogs = Realm().objects(Dog).filter("age < 5").sorted("name")

在一行调用了2个方法。对比Core Data将近10行代码。

当然,相同操作得到的结果是相同的(RLMResults 和 NSArray 基本类似),转换到Realm,由于这些查询都是很独立的,所以查询周围的逻辑只需要重构很少的一部分代码就可以了。

6.迁移用户数据

一旦你所有代码都迁移到Realm,这里还有一个突出的问题,你如何迁移所有用户已经存在在他们设备上的数据,从Core Data迁移到Realm中?

显然,这是非常复杂的问题,它决定于你的app的功能,还有用户的环境。你处理这种情况可能解决办法每次都不一样。

目前,我们看到了2种情况:

  1. 一旦你迁移到Realm,你可以重新导入Core Data framework到你的app,用原生的NSManagedObject objects去fetch你的用户的Core Data数据,然后手动的把数据传给Realm。你可以把这段迁移的代码永久的留在app中,或者也可以经过非常充足的时间之后,再删除掉。
  2. 如果用户数据不是不可替代的——举个例子,如果是一些简单的缓存信息,可以通过硬盘上的用户数据重新生成的话,那么可以很简单的就把Core Data数据直接清除掉,当用户下次打开app的时候,一切从0开始。当然这需要经过非常谨慎的考虑,不然的话,会给很多人留下非常坏的用户体验。

最终,决定应该偏向于用户。理想的情况是不要留下Core Data还连接着你的app,但是结果还是要取决于你的情况。好运!

进一步的讨论

虽然在移植一个应用程序到Realm过程中,没有真正重要的步骤,但是有一些额外的情况下,你应该知道:

并发

如果你在后台线程做了一些比较重的操作,你可能会发现你需要在线程之间传递Realm object。在Core Data中允许你在线程之间传递managed objects(虽然这样做不是最佳实践),但是在Realm中,在线程中传递objects是严格禁止的,并且任何企图这样做的,都会抛出一个严重的异常。

如此来说,对于下面这些情况,是件很容易的事情:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    //Rename the dog in a background queue
    [[RLMRealm defaultRealm] transactionWithBlock:^{
        dog.name = @"Peanut Wigglebutt";
    }];
    
    //Print the dog's name on the main queue
    NSString *uuid = dog.uuid;
    dispatch_async(dispatch_get_main_queue(), ^{
        Dog *localDog = [Dog objectForPrimaryKey:uuid];
        NSLog(@"Dog's name is %@", localDog.name);
    });
});

或者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_async(queue) {
    //Rename the dog in a background queue
    Realm().write {
        dog.name = "Peanut Wigglebutt"
    }
    
    //Print the dog's name on the main queue
    let uuid = dog.uuid
    dispatch_async(dispatch_get_main_queue()) {
        let localDog = Realm().objectForPrimaryKey(Dog, uuid)
        println("Dog's name is \\(localDog.name)")
    }
}

虽然Realm objects不能在线程间被传递,但是Realm properties的副本可以在线程中被传递。考虑到Realm从磁盘中检索objects是非常快速的,如果只是简单的通过新线程在存储区中重新refetch相同的object,这只会造成很小的性能损失。在这个例子中,我们取了对象的主键的copy,然后把它从后台队列传递给主队列,然后再通过它在主线程的上下文中重新获取该对象。

NSFetchedResultsController 的等效做法

相比Core Data的所有缺点,可能使用Core Data最充足的理由就是NSFetchedResultsController——这是一个类,它可以检测到数据存储的变化,并且能自动的把这一变化展示到UI上。

在写这篇文章的时候,Realm还没有相似的机制。虽然它可以注册一个block,这个block会在数据源发生变化的时候被执行,但是这种"蛮力"的做法对大多数的UI来说都是不友好的。目前,如果你的UI代码很依赖Realm,那么这种做法对你来说就像处理一个breaker一样。

Realm的cocoa工程师现在正在开发一套通知系统,当一些object的属性被更改的时候,允许我们去注册一个通知,来接收到这些改变。这些特性都会在Realm的Swift and Objective‑C 的未来的更新版本中。

在此期间,如果现有的通知block API还是没有满足你的需要,但是你还是需要当特定的property被更改了收到一个通知,这里推荐使用神奇的第三方库,名字叫RBQFetchedResultsController,它能模仿上述功能。除此之外,你还可以通过在objects里面加入setter方法,当setter方法被调用的时候,发送一个广播通知,这样做也能实现相同的功能。

结尾

Core Data和Realm的在展示数据的时候都是通过model objects,由于这一相似性,得以让我们从Core Data迁移到Realm时非常迅速,简单(并且非常令人满意!)。尽管开始看上去令人怯步,但是实际做起来,就是需要把每个Core Data的方法调用转换成等价的Realm的方法,然后写一个辅助类去帮你迁移用户的数据。这些也都非常简单。

如果你在你的app中使用Core Data遇到了些困难,需要些更加简单的解决办法,我们强烈推荐你尝试一下Realm,看看它是否适用于你。如果适用,请你告诉我们!

感谢阅读这篇文章。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Three.js可视化企业实战WEBGL网-2024入门指南
Three.js 是一个功能强大的 JavaScript 库,用于在 Web 浏览器中创建和显示动画 3D 图形。它的丰富 API 和模块化设计使得开发者可以轻松构建复杂的 3D 场景和动画效果。本文将详细介绍 Three.js 中的一些重要组件和模块,包括场景、相机、几何体、材质、光源、渲染器和控制器等。
用户11130883
2024/05/31
2310
three.js中的重要基础概念
Three.js 是一个功能强大的 JavaScript 库,用于创建和展示基于 WebGL 的三维图形。在学习使用Three.js来构建3D世界之前,有一些基本概念是需要牢记的,否则,在你绘制3D世界时,思绪会是杂乱无章的:
fastmock
2025/04/26
920
「冰墩墩」代码,开源了!
随着前两天冬奥会序幕的正式拉开,也成功带火了本次吉祥物冰墩墩。憨厚可爱的熊猫形象,让冰墩墩的实体公仔、钥匙扣都被一抢而空,众多网友呼吁现在真的是「一墩难求」!
对白
2022/02/11
4.6K0
「冰墩墩」代码,开源了!
Three.js深入浅出:2-创建三维场景和物体
以上demo总结来说,使用了 Three.js 库创建了一个简单的绿色立方体模型,并实现了旋转动画效果。 总结一下它的步骤:
用户6297767
2023/11/21
7290
Three.js深入浅出:2-创建三维场景和物体
Three.js - 走进3D的奇妙世界
随着人们对用户体验越来越重视,Web开发已经不满足于2D效果的实现,而把目标放到了更加炫酷的3D效果上。Three.js是用于实现web端3D效果的JS库,它的出现让3D应用开发更简单,本文将通过Three.js的介绍及示例带我们走进3D的奇妙世界。
宜信技术学院
2019/11/27
10.4K0
用 Three.js 画个 3D 生日蛋糕送给他(她)
作为整天和 UI 打交道的前端工程师,是否想在他(她)生日的时候用代码送上一份惊喜呢?
神说要有光zxg
2021/11/25
3.6K0
用 Three.js 画个 3D 生日蛋糕送给他(她)
Three.JS的第一个三弟(3D)案例
Three.js 是基于 WebGL 技术,用于浏览器中开发 3D 交互场景的 JS 引擎。
不惑
2024/04/23
3130
Three.JS的第一个三弟(3D)案例
用 Three.js 画一个哆啦A梦的时光机
在 three.js 里以向右的方向为 x 轴,向上的方向为 y 轴,向前的方向为 z 轴:
神说要有光zxg
2023/08/28
5250
用 Three.js 画一个哆啦A梦的时光机
一文搞懂如何在Three.js里创建阴影效果 |《Three.js零基础直通14》
经过上一小节,我们学会了如何使用各种类型的灯光。既然有了光,那还得有阴影,这样看起来才会更加真实。
大帅老猿
2022/11/11
7.5K0
一文搞懂如何在Three.js里创建阴影效果 |《Three.js零基础直通14》
ThreeJs 基础学习
如果你要实现一个机器人在跑步,那么机器人的头、四肢、躯干等都是要整体移动的,group可以将一系列的mesh模型组成一个整体,这样就可以实现整体移动了。
心安事随
2024/07/29
2100
Threejs入门之十六:纹理贴图和纹理材质
Texture 用于创建一个纹理贴图,将其应用到一个物体的表面,纹理对象可以通过TextureLoader(纹理加载器)的load()方法来加载一个图片。要使用纹理贴图,首先要创建一个纹理加载器,纹理加载器返回一个Texture 纹理对象,通过纹理加载器加载贴图材质 然后通过设置材质的颜色贴图map属性的值为上面的Texture来调用,下面我们创建一个立方体,并给这个立方体贴上木头材质的贴图,使其变为一个木箱
九仞山
2023/04/30
2.7K0
Threejs入门之十六:纹理贴图和纹理材质
Three.js实现脸书元宇宙3D动态Logo
Three.js实现脸书元宇宙3D动态Logo 背景 Facebook 近期将其母公司改名为 Meta,宣布正式开始进军 元宇宙 🪐领域。本文主要讲述通过 Three.js + Blender 技术栈,实现 Meta 公司炫酷的 3D 动态 Logo,内容包括基础模型圆环、环面扭结、管道及模型生成、模型加载、添加动画、添加点击事件、更换材质等。 什么是元宇宙 元宇宙 Metaverse 一词源于 1992 年尼尔·斯蒂芬森的 《雪崩》,该书描述了一个平行于现实世界的虚拟世界 Metaverse,所有现实
玖柒的小窝
2021/11/21
2.7K0
Three.js实现脸书元宇宙3D动态Logo
十分钟快速实战Three.js
本文不会对Three.js几何体、材质、相机、模型、光源等概念详细讲解,会首先分成几个模块给大家快速演示一盒小案例。大家可以根据这几个模块快速了解Three.js的无限魅力。
Vam的金豆之路
2021/12/01
2.2K0
十分钟快速实战Three.js
提示
在THREEjs中,渲染一个3d世界的必要因素是场景(scene)、相机(camera)、渲染器(renderer)。渲染出一个3d世界后,可以往里面增加各种各样的物体、光源等,形成一个3d世界:
lhyt
2019/08/20
1.1K0
Three.js贴图技巧:优化性能与效果
在当今数字化的时代,WebGL 技术为开发者们打开了一扇通往交互式 3D 图形世界的大门,而 Three.js 作为JavaScript库中的佼佼者,凭借其简单易用的 API 和丰富的功能,在创建3D场景和交互应用方面得到了广泛应用。在Three.js构建的虚拟世界中,贴图扮演着至关重要的角色。从赋予模型逼真的材质质感,到增强场景的视觉吸引力,贴图的质量直接影响着用户的体验。然而,随着场景复杂度的增加和贴图数量的增长,如何在保证贴图效果的同时优化性能,成为了开发者们必须面对的重要课题。本文将深入探讨Three.js贴图的相关知识,分享一系列优化性能与效果的实用技巧,并通过丰富的代码示例进行详细说明,帮助读者更好地理解和应用这些技巧,从而提升Three.js项目的品质。
Front_Yue
2025/03/11
2150
Three.js贴图技巧:优化性能与效果
基于 three.js 的 3D 粒子动效实现
粒子特效是为模拟现实中的水、火、雾、气等效果由各种三维软件开发的制作模块,原理是将无数的单个粒子组合使其呈现出固定形态,借由控制器、脚本来控制其整体或单个的运动,模拟出现真实的效果。three.js是用JavaScript编写的WebGL的第三方库,three.js提供了丰富的API帮助我们去实现3D动效,本文主要介绍如何使用three.js实现粒子过渡效果,以及基本的鼠标交互操作。(注:本文使用的关于three.js的API都是基于版本r98的。)
个推
2019/04/08
7.1K0
基于 three.js 的 3D 粒子动效实现
Three.js 之 Import Model 导入模型
Three.js 提供了很多原始模型,但如果我们需要更复杂的模型,最好使用 3D 软件建模,然后导入到场景中。本节我们就来学学如何导入一个做好的 3D 模型。
阿珍
2022/08/10
6.6K0
Three.js 场景创建基础
在当今数字化的时代,Web 开发已经不再局限于传统的二维界面。随着技术的不断进步,越来越多的开发者开始探索将 3D 图形引入到网页中,为用户带来更加沉浸式和交互性的体验。而 Three.js 作为一款广受欢迎的 JavaScript 3D 库,为开发者提供了强大而便捷的工具,使得在网页上创建和展示复杂的 3D 场景变得不再困难。本文将深入探讨 Three.js 场景创建的基础知识,包括其简介、引入方式,以及场景构建的关键要素。
Front_Yue
2025/03/12
1750
Three.js 场景创建基础
【带着canvas去流浪(15)】threejs fundamentals翻译系列1-scene graph
本文是three.js系列博文的一篇,第一篇文章是【three.js基础知识】,如果你还没有阅读过,可以从这一篇开始,页面顶部可以切换为中文或英文。
大史不说话
2020/05/12
1.7K0
我是如何用 Three.js 在三维世界建房子的(详细教程)
这两天用 Three.js 画了一个 3D 的房子,放了一个床进去,可以用鼠标和键盘控制移动,有种 3D 游戏的即视感。
神说要有光zxg
2021/12/10
5.3K0
我是如何用 Three.js 在三维世界建房子的(详细教程)
推荐阅读
相关推荐
Three.js可视化企业实战WEBGL网-2024入门指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验