2025-02-10 08:00:00
封面摄于 2024.03.29,腾讯滨海大厦北塔 37 楼电梯厅
与往年不同的是,2024 年年初以来,我陆续记录了大大小小的非日常的事情、以及偶尔冒出的所思所想,好似时刻都在准备着年底总结的原料。
但实际上,真到了准备开始写本篇年记的时候,又开始感觉到一阵恍惚——
这些生活的细节确实是我用心去参与的,我遵循着我信奉的想法在体验我的生活;但在大方向上,我又有点彷徨:我似乎没法认同,按现状如此下去,自己的生活状态终将往自己内心所向往的方向上发展。
我想 2024 年,我其实并没有做错什么事,但回头来看,我发现我的各种选择,都忘记了尝试缓解我一直以来的苦恼——我内心的「To Do List」仍然在变长。
一直以来,每当我有了想做的事情或者想要的东西,为了避免三分钟热度,我会用各种方式先记着,然后挂起这个想法,等待时间来检验它的必要性。
这个方法帮助我在「减少欲望」这件事上有着很大的作用。假如随着时间过去,我仍然对其抱有念想,那么我相信我能够长久地喜欢它;否则,大多数情况下都只是偶然的情感波动而已。
然而,对于我真心想要的东西,如果只是金钱消费,那是非常简单的——毕竟花钱谁不会?但对于需要消费时间的事物而言,我就显得非常难以下手了。毕竟,我还不能够把一天掰成三十个小时来用。
于是乎,一件件已经历过时间检验的事物被累积到我的 To Do List 之中,但却久久也不见有事物能被从中取出。
或许在有些总处于无聊状态的人看来,这是一种幸福的烦恼,因为他们经常需要花费不少精力去寻找新的有意思的事情。然而,这其实只是生活状态的两种极端。引用叔本华所言——
人生就像钟摆一样,在痛苦与无聊之间摇摆。当欲望得不到满足时就会痛苦,当欲望得到满足时就会无聊。
我想我如今的状态就像是被一侧不断垒高的钟摆、迟迟得不到幻想中的下落。
尽管下落所产生的摇摆可能是会使人的情绪反复遭受扰动,但我想,人生应该还是需要由这样大大小小的摇摆所组成,否则便难以避免情绪上的压抑。
但是,尽管有很多事物我迟迟得不到满足,对于 2024 年而言,我觉得我也有认真地遵从着我喜欢的方式在生活,不断完善的认识世界的框架让我的内心感到充实,我其实已经比过去更加喜欢自己。
在「解决 To Do List」这件事情上不太满意,或许这是一种贪婪的体现。
在 2024 年底,我真的如 2023 年底所想的那般,跳槽了,但心路历程则比想象中的还曲折许多。(详见《增加人生的「方差」》)
尽管我在 10 月底就已经面完所有面试,但为了避开因考核季转岗而给原部门背低绩效的风险,最终我推迟到了 24 年底才正式发起流程,并于 25 年初前往广州。
面对各个方面被重新打破的平衡,这次我又得从头开始一点点地建立秩序。这个过程必然是痛苦的,但我也有些庆幸——对于职业发展选择的内耗可以继续往后推迟了。
在过去的一年里,有几段时间经常需要加班。尽管时间紧迫,但由于这些项目的代码实现大部分是由我所主导的,我得以有机会尝试许多新的想法和技术。虽然很忙,但是每当我写出某些精巧的代码、或验证了某种编程哲学理念时,便能清楚地感觉到内心泛起一股高级的快乐感受,以至于会忘记当前是无偿加班的时间。想必这已然是进入了宝贵的心流状态。
这种沉浸感在重构代码的过程中更是如此。代码重构表面上是优化代码结构,本质上其实也是一种重新构建秩序的过程。对于一个喜欢整理东西的人而言,这种构建秩序的过程本身就能带来持续的满足感。正因为这份情感的相通,我愈发地相信透过一份代码的种种细节,某种程度上可以感受到其作者为人处事的方式以及对于生活的态度。
对于工作而言,在很多时候,我们不得不面对枯燥的重复性任务。在这些时刻,我总喜欢主动寻找一些「微小的意义」。比如,在每次完成需求的过程中,我会想着尝试引入一些新的想法或技术,这样即使任务本身是重复的,对我个人而言也仍然有所收获。这种习惯创造出了新的价值与意义,让枯燥工作的意义变得不仅仅是「出卖时间换取金钱」那样单薄。
其实令人厌烦的一直以来都不是工作本身,而是在工作本职内容之外的、影响我们专注于心流的其他事情。倘若有一份只需要专心干活的工作、以及一份可能会遭受精神内耗的工作,即使前者的工作时间更长一点,我也会坚定的选择前者。
近些时候,我偶尔会反思自己这些年的专注力为何逐渐不如以前。除了社会环境的影响以外,忽然有一瞬间,我惊讶地察觉当前这份工作的协作模式也正在破坏我的专注力。
一直以来,对于即时通讯软件而言,我的习惯是不开消息的气泡弹窗、并屏蔽所有不重点关注的群聊的消息提醒,不立即处理的事情先标记为未读或者置顶,以便于当下进行连贯的工作。
理论上,我可以主动地选择注意力在当前的工作上,或者转移到消息回复中;但实践下来,我总会每隔几分钟就突然不自觉地想起消息的事情,于是便需要检查一下通知栏里是否存在着未读消息的数字。尽管这可能只是眼镜瞟一眼图标的事情,但「忽然想起这件事」的这一行为频繁地打断着我的注意力,从而一定程度上破坏着我保持专注的能力。
我见过个别极端的人为了解决这样的问题,选择每天仅在指定的时间段统一处理消息;代价便是他人若有紧急事情时,总是需要直接电话才能联系上。我觉得这有些过于影响与其他同事的协作效率,并不能称之为是一个好的工作模式,起码并不符合我的习惯。
经过一番思索,我悲观地认为这个问题并没有很好的解决方案。但在认识到这样的问题后,我也得以更好地认识自己的专注力。在未来,我想有意识地做一些不同的尝试,看看能否在除了最激进的「放弃工作」这一方式以外,寻找将这种影响降得更低的方法。
虽然在《思考的消失》一文中,我反省了无意义信息流所造成的各种浮躁的问题;但即使是这样,在今年的很多时候,即便意识到了这个现象正在发生,我仍然难以直接从中打断,只是因为理解了问题的根源,我变得可以从中只获取放松的情绪、而不再产生空虚与焦虑。
或许,粗暴地、反人性地克制这类欲望并不是一个很好的降噪的办法。长文、长视频、播客都是比较好的减少浮躁、沉下心学习的媒介形态。用沉稳的长内容更多地代替零碎浮躁的短内容,继续奉行长期主义、培养获取心流的能力,值得接下来去有意识地尝试实践。
在面对繁杂无序的内容信息流时,「稍后再看」是一个简单轻量却又十分巧妙的好功能。
当我在查找资料时看到感兴趣但无关的短内容,我可以将其先存到稍后再看中,而不影响手头上的事情;当我看到深度好内容、但并没有合适的环境条件时,加入稍后再看的列表里,我得以在时间宽松时可以消费到已经挑选好的高质量长内容。
「稍后再看」允许用户即使身处被算法推荐所裹挟的互联网大环境下,仍然保留能够自己决定何时阅读何种内容的权力。
从 2024 年 4 月份开始,我开始尝试使用多邻国 APP 学习日语。一方面期望减少长期以来在碎片时间里对无意义信息流的路径依赖;另外一方面,也期望树立一个长期的目标,通过一种长时间的坚持行为,去向自己佐证自己拥有能够坚持长期主义的能力。
实践下来的结果嘛,先说日语学习本身,光靠每天几分钟的学习,其实有点难以形成系统性的知识体系,进步的速度越来越缓慢;而对于所谓的坚持长期主义的佐证,也总觉得好像并没有什么特别的感觉。
或许换个角度思考,这其实就是一种长期主义的体现:即便一天、一星期、一个月的坚持下来,相比过去也并没有明显的差异,但倘若相信最终目标的正确性,于是便不再在意短期的收益。
可能积少成多、终有成果,但这并不需要当下的我们来关心。我们所要关注的,其实只需要有「坚持」本身;我们所要做的,就是再多点耐心。
2024 年的 AI 工具显然已经足够成为协助工作的助手,而且它还在不断发展中。
虽然我并没有在其中投入多少精力捣鼓研究,但就是一些日常的使用上,免费的 Codeium 自动补全功能就非常实用;遇到比较独立的问题都基本可以找 Claude、ChatGPT 解决,在这些特定场景里极大地提升我的效率。
此外,Kimi 也多次帮助我处理家里处理一些事务,比如生成合同、阅读合同、解释不清楚的名词概念、简历整理等;至于诸如 Cursor 这类更加深入的 AI 编程工具,则仅仅做过试用而还没有实际融入到工作流中。
在编写本年记的过程中,DeepSeek R1 大模型再一次成为新年之际的热搜。简单体验下来,感叹该领域的发展速度仍然保持神速。其实只要将我日常写下的只言片语汇总起来丢入对话中,便可以得到一篇看似像模像样的年度总结,只不过这样就变成了 AI 的总结而非我的总结,这样的方式会大量削去文章存在的意义,所以我充其量可以参考分类组织文字的思路,而还不能允许 AI 去代替我进行文字的表达。
就 2024 年来看,仍然有很多人还并没有在日常中使用 AI 工具的习惯,没有墙的 DeepSeek 或许会成为他们入门的一个契机(虽然但是「服务器繁忙,请稍后再试」)。相信在未来这仍然是一片蓝海,专门挤出一些时间去捣鼓这些东西一定是值得的。
5 月份经过一连串的加班顺利支持一个工作项目的上线后,我忽然来了兴致,不做周全计划便一个人前往香港办银行卡、逛街。那两天可能是整年的琐碎日常里最富有激情的日子,直到现在,我也仍然对当时的那份情绪感到怀念。
引申阅读:HK 即兴一日游
自大学第一次接触苏打水后,我便喜欢上苏打水的清澈感。但一直以来,我对于苏打水并没有特别喜欢的牌子,主要是感觉口感还行的牌子,价格往往都并不便宜。
而今年在美团买东西的时候,偶然因为打折而购买了几瓶三麟苏打水,发现它的气非常足、味道不涩,口味很合适的同时价格还非常便宜(约 1.7 元 / 335 ML),于是马上买了一箱,实现苏打水自由 👍
并非广告()
因为放在家里给父母使用的电脑临时快要寿终正寝了,我赶忙做攻略,趁着双十一组了一台新的 ITX 机子给自己用,然后把自己的旧电脑退居二线回家继续服役。
新电脑的配置表一览:
类别 | 型号 | 来源 | 价格 |
---|---|---|---|
机箱 | Rider R2 5.0 | 淘宝 | 494 |
主板 | 技嘉 b650i 迷你雕 | 淘宝 | 2351 |
CPU | AMD R5 7500F | 淘宝 | 包含在上面 |
显卡 | 技嘉 RTX4060Ti 风魔 OC v1 16g | 淘宝 | 3201 |
内存条 | 科赋 雷霆 DDR5 16g 6000Mhz *2 | 淘宝 | 632 |
硬盘 | 致态 TiPlus5000 2TB PCI-E3 | 利旧 | 647 |
散热 | 利民 SI100 BLACK | 闲鱼 | 120 |
└─ | 利民 AM5 单塔扣具 | 淘宝 | 12 |
电源 | 驿晨宇玄武 650SFX | 淘宝 | 352 |
└─ | 显卡电源转向头 | 淘宝 | 18 |
风扇 | 联力 积木风扇四代 TL120 LCD 黑 | 淘宝 | 284 |
├─ | 联力 积木风扇四代控制器 | 闲鱼 | 160 |
└─ | FrostWind 8cm 风扇 *2 + 一分二线 | 淘宝 | 31 |
因为这套机子方案有一个带 LCD 屏幕的风扇,自然而然地就联想到前些日子刚看完的探讨互联网问题的实验性动画《Serial Experiments Lain》,接着就萌生了搭配 lain 的 BGM 剪一个装机踩点短视频的念头,以简单入门剪辑软件的使用。
不得不说的是,短视频的剪辑成本确实不高,花费时间最多的是在准备素材上,而到了剪辑阶段边剪边想很快就出成品了。
自毕业以来,除了疫情那次以外,我几乎很少生病。但 24 年下半年却大大小小生了好几场病。
在意识到身体恢复能力不比以前的瞬间,便同时也将意识到自己不再年轻。曾经习以为常的健健康康,如今已不再是理所当然。
或许未来将会越来越需要投入更多的精力在维护健康的这样一件事情上。想到这里,便情不自禁地想要由衷感恩当下每一个拥有健康的日子。(🙏)
对于我这种深度宅家的人而言,如果在电脑桌前坐上一天,便总会觉得身体进入一种「因为过度休息而反而产生乏力」的状态。而站立是一个很好缓解该问题的方式,但这样就没有办法再继续使用电脑。
因为彼时已经初步放下了对职业规划的纠结,并且刚续约了租房合同,我想着短时间内应该不会有搬家的变动,于是我在 8 月份购入了自租房以来就一直想要的升降桌,体验下来完美符合我的需求。
不过没想到的是,仅过了几个月,便因为工作转岗的原因,我需要打包整理房间的所有东西前往广州。
元旦连着请了假,搭乘公交前往广州寻找合适的租房。因为人生地不熟,所以我将范围缩小在上班地点的附近,这样选择更具目的性,还可以走路上下班。
然而,因为上班地点正处广州市中心地带,周围的租房价格并不比深圳南山便宜,三天看来看去,都没有看到满意的房子。最后一咬牙,抬高了自己的预算,先租下了一套单间公寓。
在这段广州看房的过程中,一个人在陌生的城市里四处奔波,恍惚间我体验到了近似于流浪的感觉——没有固定住处、没有明确的目的地、不准时的三餐,每晚还要想着明天的事情入睡。这番不太顺利的体验让我的心情有些低落,但反过来想,这也确实是一份宝贵的人生新体验。
2024 年看了 24 部当季新番、2 部剧场版、3 部老番,总体而言看得比 2023 年要少了不少。原因一方面可能是今年并没有那么多特别值得一看的作品,更主要的还是因为有大半年的时间都陷在职业规划的焦虑之中,缺乏沉下心观看内容的心情。
这一年的新番里并没有我特别钟爱的作品能够为其大书特书,如果对此部分仍然感兴趣,可以查看 我的 bangumi 2024 收藏。
出于对每日打卡式的二游(二次元游戏)游玩模式日益增长的怀疑,在 2024 年我改变了对二游的游玩习惯,实践「想玩多少就玩多少」的策略,主动拒绝每日打卡而产生的焦虑。尝试总体比较顺利,很好地减少为了上线清每日任务而在没空时也得挤时间出来的问题,从而避免了许多不必要的负担。
当然相对的,2024 年我消费在游戏上的时间可能也是历年以来最少的,这可能会继续加重我「电子阳痿」的病情(😭)
来年如果有时间的话,我希望能去专门游玩一款单机游戏,尝试寻找小时候那般对游戏娱乐的纯粹体验。
如果选一个今年听得最多的一种曲风,那么我想肯定会是 盯鞋摇滚(shoegaze)。
正好这两年,许多日本乐队都纷纷来中国巡回演出。只因为一次偶然在网易云音乐的演出列表里,我发现有我所听过的两个乐队的拼盘演出,于是在 11 月 30 号的深圳福田 BO LIVE,我独自去听了我人生中第一场乐队 Livehouse 演出——くだらない 1 日 & downt 联合巡演。
或许是因为我平时习惯于时刻审视自身的缘故,而且是第一次参与,这让我在当时有些难以忘我地投入其中,甚至产生出一定的解离感。身处巨大轰鸣的音墙其中的,是有些梦幻而有点不真实的情感体验。
对此,虽然短期来看,我无法解决因为过度习惯内省而附带的各种问题,但意识到这点的我也在尝试克服着这些问题,一点点表达自己内心中真实的情绪。在这天晚上过去,我仍然会多次回想起当时那份属于自己的情感体验,这让我已经感到十分满足。
事后当然也耳鸣了好几天(参加 Livehouse 要注意保护听力呀)
自从走出校园以来,做手工的次数就断崖式地减少了。
我曾经把原因归结为两点:
而或许是忽然怀念起这份感觉来,某天晚上我心血来潮,想要试着把很久没做的手工捡一捡。于是在陆陆续续花了一个星期的每个晚上后,我完成了一只凌波丽的不织布人偶挂件。
其实我原本想通过这一行为,证明自己还对手工这个爱好抱有热情;但在完成之后,我清楚的意识到自己当下的情绪,代表着我将会不知道需要再隔上多久,才会去做已经备好材料的下一只。即使在这次制作过程中,心流状态所带来的平静感曾令我感到惬意。
我悲观地想:或许我再也回不到从前那般热爱这些我曾经所喜欢的爱好了。
但我又总冒出一份乐观的念头:终有一天我能够自由地重新捡起我所珍视地爱好,即使这需要许多年以后。
值得庆幸的是,时至今日,我觉得自己仍然处于一种时刻学习的状态。除了对于传统意义上知识的摄取、对于社会规则的认知以外,不论是面对没见过的新事物、还是曾经见过的旧事物,我依然都能从中得出许多新的感悟,不断印证着原本并不直接关联的知识,并融入自己的思维体系中去,这让我感到满足。
今年的年记形式按着去年的想法调整了一下,试着把一年下来所有想的和做的事情都大致梳理了一遍,结果内容量比起前几年要多上太多,即便拖到 2025 年的春节结束都没能写完。
以及,内容量更大的同时也更琐碎了。对我自己而言,这样或许更能称得上是一篇年记,但我也在尽可能的平衡内容的观感,使每一小块内容都看起来言之有物。
原本在规划中,还有一块「心理上」的章节,用于总结在 2024 年里我在心理上的一些思考与转变。
我想从「欲望的死亡」这一现象开始,聊聊我当下对「乐观」与「悲观」的看法,以及「我们为什么不应该追求快乐」。
可惜,我在文字的表达与编排上遇到了一些瓶颈,为了避免本篇年记拖得太晚,只好去除这个小节。如果后面还有机会,可能会另外以一篇单独的博客发布。
而对于未来,可以预见因为工作上的变动,2025 年肯定是少不了新的人事物。事到如今,我也不再幻想能有更多可以自由支配的时间,但愿 2025 年能继续健康地活着,重新构建起新的秩序。
今年有一天看到了一句「毒鸡汤」,让我看得不由自主地说了声卧槽。虽然它的表述看起来有点悲观,但真的在许多方面缓解了我当时的焦虑。原句是如何表述的我已经忘记了,这里我尝试用自己的话来复述一遍:
我们一直不断幻想着美好的事情、但却从没踏出的真正去做的那一步,起码让我们还能持续保有「幻想最终能得到美好」的能力。
如果你已经踏出了那一步,那很好,不论结果是好是坏,新的事情都正在发生。
如果还未曾启行,那也不差,未来继续抱着这个美好的盼头,我们先过好当下的每一天。
2025-02-04 08:00:00
在 2024 年底,我真的如 23 年底所预想的那般——跳槽了,但心路历程则比想象中的还要曲折许多。
经过 2020 年的实习、于 2021 年毕业加入腾讯之后,这个行业便很快迎来三年的所谓「互联网寒冬」,整个工作与职场的氛围逐渐变得不如初见那般融洽。而我身处其中、受所见所闻影响,对于职场本身也开始萌生出了一些悲观的念头,囿于各种混乱的想法之中,不知未来如何打算。
而在经历过 23 年底一阵漫长的迷惘后,我暂时得出了「我还未及需要跳脱职场的那一步」的结论。毕竟相比于许多前辈们,我目前的职场经历可以算得是短暂而单一的,而对于这个职业而言,一旦离开便往往很难再回到原来的位置。从丰富体验的角度来说,先尝试改变一下环境或许是更合适的选择方案之一。
但是,尽管自 3 月份开始,我便有意识地尝试准备简历与刷题,但在我脑海里,幻想中的「换一份更加 Work-Life Balance 的工作」的念头与结合现实情况的「换一份更适合职业深入发展的工作」的念头两者之间的冲突也随之被搬到台面上来。这份矛盾持续地影响着我难以做出果断的决策,再加之工作方面一直以来不间断的繁忙,以至于直至 10 月份,我的简历甚至都还没有成型。
可能这就是整个社会经济增速放缓、集体纷纷右转(保守主义)的大背景投影在我个体身上所显现的最大的困境:
如此漫长的二择困境,曾一度让我决定放弃选择、保持现状、减少焦虑,以期望将工作时间以外的注意力重新交还给生活,回归到我所认为的有价值的地方。我清楚地明白在当前的环境与条件下,我实质上失去了主动做出改变的动力与勇气,因为不管是哪种选择,我都无法推演出其是否更加正确的结论。
而最终帮助我做出选择的还是一个偶然的外力:恰逢国庆假期得以时间休息之时,我收到了前同事的一个公司内部活水面试微信的内推机会,工作内容显然比当前的工作要更加具备价值,薪资待遇当然也会有所提升,但代价就是将要付出更多的时间与精力投入其中。
在短暂的犹豫后,我抱着先试试看的心情选择接受了这次面试机会。起码借助这股外力,我得以有了阶段性目标,能够快速完成半年都没完成的简历整理。「即便面试没有通过、或者最终我没有接受 offer,我仍然会有所收获,那么对此我便没有什么好计较的」——我如此想到。
或许是运气,或许是巧合,整个面试的流程下来都比想象中的要顺利许多。很快,我就得到了原本并不在考虑范围内的 offer。
许多人求而不得的 offer,我何有不接受的道理?然而,如果接受它,那么这代表着我将换一份工作内容、换一批同事,甚至换一座生活的城市,这对于我的现状而言是具备挑战性的。
在做出一个选择之前,我总是习惯于去找到一个能够让自己认可的理由,这样未来的我便不再会后悔当初的选择。而在面试的这段时间里,我偶然阅读了孟岩的一篇公众号文章,他将自己的一期播客的内容以文字的形式整理成了一篇长文,介绍了自己的一些生活态度。而在这其中,有两个观点让我记忆犹新:
在这个世界上,那些长期的、宏大的目标,往往需要一些不容易预见到的、非线性的过程才能达成。
我们不太可能预测所有的可能性和结果,也不太可能预测到中间的路径,特别是那些可能对我们的目标产生关键影响的事件。
无论是我们说 make things happen,或者说 gradually, then suddenly,其实都是在说这件事。
如果是这样的话,我们需要一些什么呢?
我想首先是可以允许放弃一些对未来的计划,
敢于允许自己去做一些自己真正感兴趣的事情,
敢于允许自己去做一些「方差大」的或者说从来没做过的事情,
保持开放和灵活,
对新的信息或者说信号保持敏感,
并且能够根据这些信号来进行调整。
当然,我们还需要时间。
在时间的流逝中,这些东西都会慢慢积累,会有那么一天,我们可以 connecting the dots,看到事物之间不那么明显的联系,能够从巨大的房间里面找到那些关键信息,能够看到那需要的关键一跃。
——孟岩 《让奇迹发生》
关于孟岩对其观点的详细论述在其原文中已经非常全面,这里不再拾人牙慧进行复述。这份观点很好地缓解了我对于如何做出选择的困扰、对于未知的恐惧、以及对于失败的焦虑。
如果说伟大是无法被计划的,那么我们便不再需要保证我们的每一次选择都是绝对正确的。在事情的一开始,我们应该允许自己去做一些更加跳脱于日常的事情,去尝试增加人生的「方差」、拥有更多的可能性。即使某次选择看起来错了,最终,它也将会成为自己生命中的一部分,成为某种未来不可或缺的垫脚石。
于是我不再害怕变化,我相信这个选择最终会为我带来有别于现状的新的收获与体验。
当然,跳出舒适圈是反人性的,这份「痛苦」对于转岗广州后的当下的我而言体验自然尤为深刻;我所做的事情也并不完全符合孟岩老师的全部观点,因为我违反了自己内心的期望、正让自己变得更加难以协调生活的比例,这实际上让我有些「后悔」这次的选择。
但我又暗自相信,随着适应期过去,我会重新变得不再后悔,未来的我能够在其中重新找到新的平衡,或着找到新的出路。
这只是我的一次增加「方差」的尝试。我时刻庆幸着未来的我仍旧有得选。
只要还有得选,人生就总不至于陷入被动之中。
封面:属于原部门的三台测试机,恢复出厂设置以准备退库
2024-07-04 08:00:00
信息时代下,图像抠图技术已经成为了一种不可或缺的技术,被广泛应用于视频直播、电商产品宣传、平面设计、背景替换等场景中。它通过将图像中的前景目标与背景软分割,实现了前景目标图像的独立提取,同时保留边缘的透明度。
传统的抠图方法通常依赖于 PS 等图像处理软件,需要人工手动进行前景目标的抠取。人工抠图可以得到高质量的结果,但也需要花费相对应的精力。面对需要大量抠图的任务场景,人工抠图的成本变得不可忽略,所以抠图自动化具有很高的应用价值。
在计算机领域,图像抠图(Image matting)是一项基本的计算机视觉问题。通过计算机计算实现的智能抠图应用,让我们仅需输入图像,算法就能自动完成前景目标的抠取。与图像分割(Image segmentation)不同的是,图像分割本质上是一种分类任务,其结果像素点透明度只能取值 0 或 1,其分割边缘为硬边缘;而图像抠图则可看为是一种回归任务,其结果是某像素点为前景的 alpha 权重概率,所以抠图结果的边缘过渡较为自然,对于毛发等边缘的细节上的保留效果要好很多。
Web 前端 AI 图像分割:Segment Anything | Meta AI
Web 前端 AI 图像抠图:Xenova/remove-background-web
随着这些年的发展,基于深度学习的图像抠图算法准确性和效率大大提升,逐渐从传统抠图算法中脱颖而出,成为抠图应用的主流技术。
本文的重心在于抠图算法的实际应用,这部分仅作背景简单了解
目前流行的图像抠图算法大概可以分为两种:一种是基于先验信息的方法,另一种是无需先验信息的方法。
在图像抠图领域中,常见的先验信息可以是 Trimap(三元图,一种将图像分为前景、背景和未知区域的标注信息)、无人的背景图像、人物姿势信息、视频临近帧等。基于先验信息的模型网络使用先验信息与图片信息共同预测 alpha。2017 年由 Adobe 提出的 Deep Image Matting 模型,就是基于 Trimap 的首个将深度学习应用于图像抠图任务的算法,在当时取得了 State-of-the-Art 的水平。
Deep Image Matting 使用了经典的 Encoder-Decoder 结构作为基本框架:预训练的 VGG-16 网络作为 Encoder 部分,对输入图像进行特征提取;Decoder 部分由多个反卷积层和 ReLU 激活函数组成,这些层用于逐步将编码后的特征图恢复到原始图像的分辨率,得到较为粗略的前景蒙版(Alpha matte)。最后 Deep Image Matting 还使用了一个小型的卷积网络,用来提升前景蒙版的精度与边缘表现。
另一种无需先验信息的抠图算法,网络仅根据图片本身信息对 alpha 进行预测。虽然效果往往不如第一种,但因为对于实际应用更加友好,所以是目前比较主流的研究方向。
MODNet 是香港城市大学与商汤科技于 2020 年发表的无需绿幕的实时人像抠图网络。它很好的在不使用 trimap 的情况下获得了较高的精度,同时保证了实时性,能够应用于实时视频抠图。
MODNet 作者认为神经网络更佳适合学习单一任务,所以他将模型的学习训练分为三个部分:
MODNet 设计的轻量级网络结构大大减少了抠图计算量,降低了抠图模型的使用门槛同时保留了较高的抠图精度,具有较高的实用性。
尽管 AI 算法研究本身具有一定的门槛,但我们想要开发相应的应用则并不困难,因为网络上有着许多现成的预训练模型,也有现成的 SaaS 服务可供直接使用,在这些已有的能力上去做延伸,我们得以低门槛地创建简单的应用。
虽然使用 AI 技术自动抠图在业界的实际应用已经比较普遍,但是大部分的应用服务都是将模型部署于 GPU 服务器上,基于云 API 对内或对外提供服务。考虑到如果希望在内部场景提供相关的抠图能力,则属于低频功能,单独部署一台服务器将导致其绝大部分时间都处于空置浪费状态。
随着 AI 技术的进步以及用户设备性能的提升,此类 AI 抠图应用已经可以实现在前端内部进行闭环,使用纯前端技术来实现,在较低的性能需求的情况下可以得到相对较好的抠图结果,同时无需额外的 GPU 服务器开销或使用第三方云 API 的费用开销。
类别 | 优点 | 缺点 |
---|---|---|
前端 | 前端内部闭环,处理图片时无前后端通信与传输开销;AI 端侧部署是未来主流的发展趋势之一,充分利用性能越来越好的用户设备 | 首次使用需要加载模型文件;性能受限于用户设备,不宜使用过于复杂的大模型 |
后台 | 性能无瓶颈,可以使用复杂模型 | 需要有日常的服务器租用开销,服务器性能与费用之间需要进行取舍 |
司内/司外现成云 API | 已经提供好基础能力可直接使用 | 受限于第三方,不够灵活,不一定会持续维护更新;司外接口涉及隐私问题;每次使用都会产生费用 |
接下来我们都以前端部署 AI 应用为背景进行讨论。
简单搜罗了网络上开源的抠图相关方案,做了一些简单的试用对比,得到对比表格如下:
名称 | 优点 | 缺点 | 门槛 | 采用 |
---|---|---|---|---|
MODNet | 模型体积小(25.9MB)、推理速度快、效果总体良好、有封装好的预训练模型 | 边缘比较软,会带一点背景色,需要看情况另外优化 | 低 | ✅ |
RMBG-1.4 | 效果总体良好、边缘清晰,不仅限于人像抠图、有封装好的预训练模型 | 模型体积大(176MB) | 低 | ✅ |
modern-rembg | 兼容 rembg 的前端版本,支持多种现成预训练模型(u2net、isnet-anime等),可选项多 | 各个模型各有优劣,不够通用 | 中 | ⭕️ |
tfjs-models/body-segmentation | 模型体积小(20MB以内) | 仅提供了最基础的底层能力,需要自己封装并大量优化,否则效果不佳 | 高 | ⭕️ |
RobustVideoMatting | (未试用) | 特供于 Web 实时渲染的预训练模型精度很低,需要拿其他的模型进行转换;仅提供了基础底层能力,需要自己封装优化 | 高 | ⭕️ |
imgly/background-removal-js | 功能完善,开箱即用;不仅限于人像抠图 | 模型体积大,推理速度很慢,抠图效果一般 | 低 | ❌ |
transformers.js 是一个和深度学习相关的 JavaScript 库,基于 onnxruntime-web 的能力在浏览器上运行模型。该库提供了简洁的 API 和丰富的预训练模型,使前端开发者能够轻松地在浏览器中直接使用和运行预训练好的深度学习模型。
综合开发成本以及时间考虑,我们选择使用能够支持 transformers.js 的 MODNet
和 RMBG-1.4
两个抠图模型进行简单的实践。
我们都知道跑在浏览器的 JS 代码,在性能方面客观上难以和由静态语言编写、直接运行在系统进程里的程序相媲美。特别是在 GPU 的使用上,浏览器在过去通常只能通过 WebGL 实现。因为 WebGL 主要设计用于渲染图形而非通用计算,且性能上受到了硬件以及浏览器的限制,所以并不擅长计算密集型的深度学习任务。
好在,2023 年 5 月份 Chrome 在 113 版本中正式发布了 WebGPU API,使得我们能够在浏览器中使用更简洁易用的 API、更强的计算能力去执行图形和计算任务。
现在(2024 年)WebGPU 还是属于一项实验性技术,只在最新的部分现代浏览器上有支持。但好在 PC 端的现代浏览器都会自动更新到最新版本,所以普及率的问题比移动端要好。
transformers.js 目前也正在适配 WebGPU,预计在 V3 版本中正式发布对 WebGPU 的支持。从这里可以看到 WebGPU 与 WASM 的实时性能对比。下图是用 MacBook Pro Apple M1 Pro 笔记本对于文本嵌入(Text embedding)任务跑出的结果,大概是 10.26x 的性能差距。
transformers.js 的 maintainer 也给出了一个 WebGPU 版本的前端 AI 抠图 Demo,可以从这里访问体验:Xenova/remove-background-webgpu
由于 V3 版本还没有预计正式 release 的时间点,目前想要通过 transformers.js 使用 WebGPU 能力尝鲜的话,需要直接从 github 源安装 v3 分支成依赖使用。(2024.08 更新:作者新增了@huggingface/transformers 包发布预览版,可以直接安装 @huggingface/transformers,不再需要处理从 github 下载依赖的未编译问题)
# npm install xenova/transformers.js#v3
npm install @huggingface/transformers
使用时,需要指定 device
为 'webgpu'
,且 dtype
只支持 'fp32'
和 'fp16'
(精度不同)。
import { AutoModel, AutoProcessor } from '@xenova/transformers';
// Load model and processor
const [model, processor] = await Promise.all([
AutoModel.from_pretrained('Xenova/modnet', {
device: 'webgpu',
dtype: 'fp32', // or 'fp16'
}),
AutoProcessor.from_pretrained('Xenova/modnet'),
]);
如果需要兼容不支持 WebGPU 的浏览器,可以通过判断
navigator.gpu
是否存在进行区分。目前,在 TypeScript 项目中引用navigator.gpu
,需要引入@webgpu/types
补充类型定义。
这里简单写一个抠图 DEMO 获取输入图片的前景图像的 ImageData
对象,就能看出 transformers.js API 在使用上的方便程度:
import { AutoModel, AutoProcessor, RawImage } from '@xenova/transformers';
// Load model and processor
const [model, processor] = await Promise.all([
AutoModel.from_pretrained('Xenova/modnet', {
device: 'webgpu',
dtype: 'fp32',
}),
AutoProcessor.from_pretrained('Xenova/modnet'),
]);
function demo(url: string) {
// Load image from URL
const image = await RawImage.fromURL(url);
// Pre-process image
const { pixel_values } = await processor(image);
// Predict alpha matte
const { output } = await model({ input: pixel_values });
// Get output mask
const mask = await RawImage.fromTensor(output[0].mul(255).to('uint8')).resize(image.width, image.height);
// Composite the original image with the alpha matte
const { width, height, data } = image.rgba();
const imageData = new ImageData(new Uint8ClampedArray(data), width, height);
for (let i = 0; i < width * height; i++) {
const alpha = mask.data[i];
imageData.data[i * 4 + 3] = alpha;
}
return imageData;
}
分别使用 MODNet 和 RMBG-1.4 两个模型进行测试,得到的输出结果对比如下:
输入图像(1024x683) | MODNet 抠图结果(耗时 295ms) | RMBG-1.4 抠图结果(645ms) |
---|---|---|
![]() |
![]() |
![]() |
输入图像(1098x1098) | MODNet 抠图结果(耗时 327ms) | RMBG-1.4 抠图结果(652ms) |
---|---|---|
![]() |
![]() |
![]() |
抠图结果放在透明白色底背景对比不明显,需要放在深色背景下对比
注意模型推理的耗时状况,可见在 WebGPU 的加持下,在 Web 端侧运行 AI 抠图模型是完全可行的。
在我司的道具打赏业务中,展示打赏爆灯特效需要使用到从媒资库拉取的明星头像图片,而从媒资库拉取的明星头像通常带有相对复杂的人物背景,不一定有纯人物的透明背景人像素材,不适合直接用于爆灯特效场景。
以往的常规做法是:由运营同学再找设计同学协助,针对这些非透明背景的明星头像重新抠图,使用新图干预配置结果,这导致设计和运营同学的工作量大大增加。尤其在跨年直播、星光大赏这种明星人数非常多的情况下,手动抠图并配置的工作量大、流程繁琐,出错的概率较高。
另外,手动抠图的质量也不总是十分完美的。如果为了追求效率或者要求标准不高,手动抠图的质量也会参差不齐。
所以我们希望应用 AI 技术实现人像一键抠图去除背景,减轻设计工作量,提升运营配置效率。在将这些技术应用到具体业务的过程中,我们也能与现有业务进行有机的结合,以更直接和贴切的方式解决业务的实际痛点。
为了后续能够将同一套抠图能力尽可能简单地复用到多个场景的业务中去,我们将核心的抠图能力封装为一个基础 SDK,隐藏不同模型在使用上的差异,对外提供简易的 API:
// Create remover
const remover = createBackgroundRemoval('rmbg'); // or 'modnet'
// Model initialization load
await remover.load();
// Execute matting task
const result = await remover.run({
input: image,
output: {
type: 'data-url',
},
} satisfies RemovalOptions); // result is base64 image data URL
// Options definition
interface RemovalOptions {
input: HTMLImageElement | ImageData | RawImage | Blob | URL | DataURL | string;
output?: {
type?: 'blob' | 'data-url' | 'image-data';
};
}
为了实现更多拓展性的功能,我们在此基础 SDK 上,二次封装了一个带有弹窗 UI 组件的 SDK,提供通用的交互界面与常用的调整项,支持抠图结果预览、切换模型、微调参数、批量抠图等功能。
设计稿初稿参考:
使用示例:
removeBackground({
input: pic, // pic 支持数组类型或者单个元素传入
onConfirm: (value) => {
console.debug('onConfirm', value); // 当 pic 为数组时,value也为数组;反之亦然
},
});
参数的类型定义:
type ImageSource = HTMLImageElement | ImageData | RawImage | Blob | URL | DataURL | string;
interface PopupParams {
/** 输入图像 */
input?: ImageSource | ImageSource[];
/** 输出图像的配置 */
output?: {
/** 输出图像类型 */
type?: 'blob' | 'data-url' | 'image-data';
};
/** 抠图模型类型(默认 rmbg) */
model?: 'rmbg' | 'modnet';
/** 额外功能选项 */
options?: {
/** 上传图片的数量限制(不启用上传/单张/多张) */
uploadType?: 'disabled' | 'single' | 'multiple';
/** 是否支持用户手动选择抠图模型 */
modelSelectable?: boolean;
};
/** 抠图完毕返回结果时回调 */
onConfirm: (value: ResultType | ResultType[]) => void; // ResultType 取决于 output.type
/** 失败回调 */
onError?: (error: unknown) => void;
/** 取消抠图关闭弹窗时的回调 */
onCancel?: () => void;
/** 弹窗关闭时的回调 */
onClose?: () => void;
}
除了 transformers.js 的方案以外,还有许多其他的抠图模型与方案也都值得一试。往往不同的场景、不同的限制条件下,不同的模型能够取得更好的效果。
如果要准确的评价算法模型的抠图效果,还可以在网络上下载一些抠图数据集(例如 PPM-100),以量化的标准(均方误差 MSE、平均差 MAD 等)衡量模型的表现。
2024-06-20 08:00:00
经过连续一个多月的高强度加班赶项目上线后,终于得以有时间稍微休息一下,于是请了两天工作日的假,准备处理先前一直搁置的事情。而在休息的过程中,我忽然想起办香港银行卡的事来。
原本先前是想着等「工作上的事情」尘埃落定了再去着手处理,但因为这个「工作上的事情」进度推进得实在太慢,导致我不得不开始重新思考事情的优先级。办卡作为一个「重要不紧急」的事情,虽然我当下还没有强需求,但是最近和同事聊天,提到「银行卡之类的并不是一办下来就让你随便用的,容易触发风控,最好先保持较长时间的正常使用」,于是我觉得还是得尽快找个时间搞下。
一开始想到这回事,就觉得正好可以趁着工作日人少,直接去把卡给办了。但是在研究攻略的过程中,发现得准备港币现钞、预约银行办卡业务、打印地址证明等等。研究到了这里已经是大晚上了,显然如果想要准备齐全,肯定是没法趁这次休假的工作日去办卡了。
但一想到这件事还要继续挂在心里半个月,又觉得实在是有些膈应。而且如果能趁这次机会直接办好,回来还有两天周末可以休息,可以说是非常舒服的安排了。
于是我继续研究攻略到凌晨两点多,得出了这样一套结论:
以前,我的出行都会提前做好详细的规划,尽量避免预料之外的风险。但这样高成本的准备也导致做一件事情从规划到完成需要经过很长的时间。于是这次我告诉自己,偶尔也该尝试放下过多的顾虑,直接开始去做,而不是长久停留在计划中。如果一件事的最坏情况都在可以接受的范围内,那就没有什么好担心的了。
想到这里,即便我还没完全定好要去哪间分行办理、坐什么交通工具、哪些细节需要注意、办完后应该去哪里逛,也觉得这卡确实今天非办不可了。
根据早上八点半抵达香港的时间倒推,得到我应该六点半起床的时间安排。看了眼只剩下三个小时的特种兵睡眠时长,于是我便不敢再多花时间继续研究攻略了,简单收拾之后就很快上床睡觉。
虽然深圳湾口岸离我住的地方更近,但在睡前确定起床时间时,发现深圳已有通往香港的高铁线路,仅需 14 分钟便可从福田抵达西九龙,且工作日早晨的座位充足无需抢票,于是便欣然确定选择到西九龙附近进行办理。
这次我想办的有三家:中银香港、汇丰、ZA BANK(众安)。
对于一般人,这样的配置应当就足够应对绝大部分需求了。
考虑到直接再西九龙高铁站附近的分行办理肯定会有很多人,所以我随便上了一条港铁。然后查到两站外的「奧運」站附近就有中银香港和汇丰的分行,又匆忙在该站下车。
不过因为太久没来香港,而谷歌地图的方向定位又差劲(经常不显示用户的面朝方向),在找路上来回兜圈子花费了不少时间。待到 9 点 20 分赶到一家在商场里的中银香港分行取号时,已经要排队等七八个号了。
取号前,大堂经理会先简单询问开户目的、确认相关证件是否准备齐全,然后让你先扫个二维码填写一些信息。填完后在商场内部转悠了半个多小时,见排队进度几乎不变,于是决定折返回港铁附近的汇丰银行取号。
汇丰的排队人数相对就少上一些,不过也等了近 40 分钟才轮到我。仅需身份证、港澳通行证、通关小票,礼貌的柜员小哥一通丝滑的操作,借记卡直接当场给到,而信用卡则需要晚些审核通过(卡内入金一万港币以上)后邮寄,便愉快地完成办理。
拿到卡后,这次办卡之旅就有了保底。不过赶回中银却发现自己已经过号 10 个号了,无奈只能重新取号。
在等待的过程中,我发现每个人办理的花费时间虽然不定,但基本都很长,所以可能排队号 1 个小时都不带变;但是一旦有办理完的就会开始很快地轮过叫下一号,这就导致如果号排前面的人不在现场,就很容易一波轮过去好多个号,也就没法通过当前的排队人数很好地估计啥时候能够轮到自己。
大堂经理也是一位很有心的阿叔,记得我取的号码,看到我反复路过银行门口查看一直没变的排号,就推荐我先去解决午餐。
香港现在实行限塑令导致麦当劳也不提供一次性手套,大家都直接上手拿着汉堡吃
饭后一边继续逛商场、一边偶尔回来瞄一眼叫号进度。逛到一家「千葉玩具屋」(后面发现是连锁店),挑了两个惠惠的谷子(Goods,即周边),基本是按原价 1.5 倍以上在卖,不过当作小纪念品的话就倒还可以接受了(-78 HKD)。
等待排号的过程中也是顺便完成了 ZA BANK 的开卡申请,并规划接下来的逛街路线,所以时间基本也很充实,没有太多浪费。
值得一提的是,ZA BANK 需要扫描港澳通行证背面的签注信息(带二维码),而我签的那个自助签证机印刷不太好,出来的内容有些错位,上传直接没识别成功,还好再我多传了两遍后也给通过了。
PS: ZA BANK 办卡最近一直都有返现活动,注册时如果没有其他邀请码,可以填我的邀请码「GCGDA9」
中银香港的卡办起来要比汇丰麻烦一点,柜员上来就会问开卡目的,这里不能说错话,否则容易被拒。声明是投资的话,需要出示对应的股票投资记录,我给看了富途 APP 里的持股信息,柜员还会要求让你证明这个号的实名信息是你的(我是在 APP 的客服中心里找到开户资料的入口,柜员认可了)。
而关于地址证明的问题,因为我填的是身份证上的地址,柜员专门说明了一下这种情况他们会以身份证作为地址证明,这样就不需要再提供额外的地址证明了(信用卡账单/水电费账单之类)。
然后就是较长时间的资料填写过程,最终也是顺利通过,卡后续以平邮的方式寄到上面所填写的地址。平邮没法查邮寄进度,上面也没写联系电话,只会送到地址对应的邮箱中,所以也有可能会丢失。如果迟迟没有收到,就得联系客服重新改寄挂号信了(后记:我大概是 20 天后成功收到信封)。
走出银行时,已经下午三点了。
来都来了,正好查到旺角这一块有不少动漫爱好相关的店铺,于是决定顺着弥敦道一路北上,开始扫街之旅。
我参考的是随便刷到的小红书攻略,最终按照「現時点 - 信和中心 - T.O.P Shopping Mall - MOKO - Moviemarks - 玩具模型倉」的顺序,一直逛到手机电量告急才作罢。
現時点的感觉类似于深圳的东门动漫城,比较挤比较杂,有很多小店铺贩卖各种周边(手办居多),在过道边上的格子柜看着应该有好价的中古手办可以淘一淘。
当时人太多了不好意思拍照,借张网图吧 😢
信和中心我只逛了 B1 层,除了亚文化爱好周边以外,有很多最新的 CD 专辑、画集、大尺度写真集可以买到,就是画集卖的确实是贵(翻倍卖)。总体而言还挺推荐逛的,而且我还错过了第二层,应该会有挺多漫画店。下次路过的话我还想再去看看。
T.O.P 则是个很多层的小商场,聚集了各种年轻人喜欢的亚文化爱好店,而且明显感觉到来逛的女生比前面去的那几个点要多。
T.O.P 的次顶层有 BANDAI 的扭蛋店(价格翻倍卖),还有家「らしんばん」(罗针盘)。在扭蛋店里绕了两圈,看到有物语的机子,手痒扭了一发,结果正好抽到了最想要的小忍!
尽管是用 30 HKD 换个「时尚小垃圾」,但那一刻也会忍不住地开心。(笑)
在罗针盘可以淘一淘中古谷子,店的规模不是很大,虽然价格肯定比不了日本,但胜在比去日本方便。偶然发现在一处角落有两框同人本,兴冲冲地翻找起来,结果除了表面的两本以外其他都是女性向,~~而且没有 R18 本,~~失望地走出店铺。
因为出发前一天只睡了三个小时,一天逛下来已经开始有点低血糖了,于是在 T.O.P 商场的负一层简单吃了顿咖喱饭(-60 HKD)。
饭后,继续前往 MOKO。MOKO 则是一个比较常规的商场了,有几间二次元相关的店铺,不过收获不大(可能是我没怎么逛到)。这里也有一家罗针盘,但平均价格比前一家还要贵,不太推荐专门跑过来逛。
题外话,走出 MOKO 商场负一层进入到地下通道的一瞬间,让我幻视「化物语」里姬丝秀忒的一个场景镜头
本来还想出发逛一逛深水埗,但到了这里充电宝已经没电了,为了避免失联,于是准备行程告一段落,坐巴士返回深圳湾口岸。不过在前往巴士站点的过程中意外发现会路过 Moviemarks,便决定来都来了就顺路逛逛吧。
Moviemarks 是开在路边的一家店铺,里面有着非常全的电影海报收集,在这里可以买到各种有在香港上映的电影所对应的宣传海报,还有一些电影特典、周边之类,对于电影收藏爱好者而言可以算是宝藏店铺了。店里也有一块日本动画电影作品相关的区域,光是坐在店里随便翻翻集册、感受店铺的装潢氛围,就感觉挺治愈的。
离开 Moviemarks,走到站点附近,意外发现站点处就在之前在攻略看到过的「玩具模型倉」店铺门口。虽然我目前还没有入模型坑,对其不太了解,但离巴士到站还有一点时间,于是简单进去逛了逛。
店内的货架摆满了各种拼装模型盒子,还贩卖各种拼装制作模型所需的工具(喷笔、油漆、钳子之类),以及搭了一些好卖的景品。听说这里的促销商品价格比在网上买还便宜,倘若是一名模型爱好者,想必是值得一逛的。
没拍照片,引用个官方 SNS 贴过的照片:
坐上 58X 巴士,手机的电量已经不支持我再继续使用了,只好先关机,因此也差点坐过站。幸运的是,在屯门换乘的前往深圳湾口岸的 B3X 巴士每个座位都有 USB 充电接口,成功续上了 7% 的电量,顺利支撑到过关打车回家。
对于住在深圳的人来说,显然,去香港办卡也不是什么很麻烦的事。做记录可以,「上价值」就感觉好像有点稍显夸张。但对我而言,它确实完全跳出了我休假前的计划,给「事事都被规划的日常」带来了超出这点小事本身的新鲜体验。
我想我总是热衷于得到各种新鲜的体验,而这也正是驱使着我在前一天凌晨忽然决定不做预约与详细规划就匆忙前往香港的重要理由之一。开卡这件事当然并不着急,但因为平日看到那些更随性、不怕生的人,用自己的方式热爱着自己的生活、充满激情,所以我也想简单尝试一下,仅此而已。
乘上与平时相反的电车,为了去看未曾见过的风景——《比宇宙更远的地方》
在最近的一些日子里,我花了不少精力告诉自己应该追求内心的平静、而不是追求快乐本身,避免陷入过度享乐的空虚之中。而现在看来,除了维持内心的平静以外,还应该持续保有产生「激情」的可能性。
激情是生命力量的源泉,当内心对于正要去做的事情充满足够的激情,就会神奇地发觉平时所抵触的那些麻烦事,也可以持续保持以正向的情绪去完成。
后注
开卡流程等相关信息具有时效性,请留意本文的发布时间。有相关计划建议再自行补充查阅更多攻略信息。
2024-04-09 08:00:00
注意:本文所记录的页面现已暂停使用,仅保留体验地址:https://v1.ceynri.cn/
关于本文所提到的页面对应的搭建心路历程,可以先行阅读《记第一次建站的心路历程》。
本文全文较长,故提供简要的目录说明内容结构:
本站的实现对我而言是一次较为完整的学习与实践,对本站所用到技术相关内容进行简单的记录。
TweenMax.js 提供了丰富的缓动动画效果,具有较高的性能与非常好的兼容性。本站在绝大部分元素的以下属性的变化上,都使用了 TweenMax.js 进行动画处理以求达到流畅的视觉效果体验:
使用最多的是 TweenMax.to()
函数,其能接受 paused
参数将动画保存下来,然后对保存的函数调用 play()
与 reverse()
方法实现动画的正向/逆向播放。
reverse()
虽然大大简化了代码,使代码更加漂亮,但也给我带来了不少的 bug(主要是动画相互冲突的 overwrite 问题)。
光标代码是我写的最大的一个 js 文件,其大致流程是:
绑定页面内的光标元素组 -> 设置相关属性 -> 生成动画 -> 为不同元素的事件绑定相应的动画
为了设计光标的交互效果改了不少的版本,更麻烦的是鼠标这种掌握在用户手中的元素很容易产生许许多多的 bug,调教好它是我花费时间最久的一个部分。
因为页面的内容比较重视整体,所以让用户看到未加载完成的页面一点一点并不连贯的加载并不美观,引入载入动画,让其在页面加载完成后再显示主题页面,在视觉上使加载页面的过程是连贯的(因为加载中时的页面内容是被遮挡住的)。
但坏处是如果用户访问页面时有文件请求被阻塞、或者网速过慢,使页面一直处于加载状态,可能会导致整个页面无法浏览,一直被载入动画的遮罩挡住。解决办法是超时时引导用户重新刷新页面、或者强制播放载入完成动画显示页面的已加载部分。
滚动效果方面分为了平滑滚动、渐变滚动和视差滚动三个部分,分别负责不同的效果。
其中,平滑滚动的实现是将整个页面的所有内容作为一个元素包裹起来,并且不与 body 元素绑定,即浏览器窗口滚动时,并不会造成页面的滚动,从而屏蔽默认的滚动效果。再用代码实现平滑的滚动效果,让页面接收到滚动事件时执行相应的缓动动画。
渐变滚动指的是页面的第二部分——「about」部分,文字的渐入与渐出效果,通过监听当前文段在窗口坐标系下的坐标改变透明度实现。
视差滚动则对于特定的元素监听滚动的距离,将其乘以对应的倍率即可。简单的元素可以使用 CSS 的 perspective
属性实现,但是如果元素稍微复杂一点、超出了一层的父子关系,则使用 JavaScript 计算对应的 transform
值来实现更加合适。(效果见上面的「渐变滚动」)
视差浮动是对鼠标窗口坐标的监听,改变不同元素的空间坐标,增强元素的空间感(仅运用在第一部分(主标题)和背景中)。
3D 透视指的是 My Works 部分有关鼠标于 work 方块的交互。首先实现的是基本类,允许 work 方块根据鼠标与其的相对坐标进行三维空间上的旋转,同时有 z 轴方向上的位移,以在旋转中能够产生透视感;再写专门的类去对应不同的 work 方块,增加它们之间不同的交互特性,给用户更加新奇的交互感。
进度条在这里承担了进度条的外观和滚动条的功能,所以在交互逻辑上需要在一般的滚动条基础上做改进。假设根据鼠标按下的位置划分为「在进度条已达到位置」和「进度条未达到位置」,则:
大量的交互动画往往会带来更大的性能问题,优化它们是非常必要的,毕竟流畅是网页浏览体验中最重要的体验之一,失去流畅感,即便再有意思也会让人觉得很可惜。
本网页陆续采用了几个角度对网页的流畅性进行了性能优化:
requestAnimationFrame
EventListener
{ passive: true }
优化代码结构是最朴实的方法,这一点不论在什么阶段都应该注意它。大的方面可以讲代码复用、方法提取,小的地方可以是 DOM 元素引用保存、if 判断结构优化等等。优化代码是一个很泛的目的,通过不断地学习、阅读优秀的源码,我们可以学到更多的精彩的代码写法。
对于做 JS 动画,requestAnimationFrame
是一个很棒的 API。
与 setTimeout
相似的是,它们会被「定时」执行,但不同的地方在于:requestAnimationFrame
会在浏览器进行每一帧的渲染之前执行并完成。
而与各种 EventListener
相比,requestAnimationFrame
一般在 1s 内只会执行 60 次,即 60FPS。EventListener
则没有频率限制,如果执行太快,超过了屏幕刷新率,会产生无效的渲染和重绘,反而导致页面的性能下降,出现卡顿。
而且 requestAnimationFrame
从语义上告诉了浏览器我们要执行一个动画,浏览器会去优化它,还可以根据当前 CPU 负载情况调整帧数。
减少不必要的 EventListener
也是有效的方法之一。
我们不应该滥用 EventListener
,这会导致一个事件的发生会执行更多的代码,如果我们仅仅为了在不同的代码区域获取鼠标位置而反复添加 EventListener
,会产生较大的代码冗余的情况。
另外,可以不在 EventListener
内执行的代码都应该提出来放在外边执行,尽可能精简一个 Event
触发所要执行的代码。
对于不同的 EventListener
,我们也要根据触发频率来不同的对待。像鼠标移出事件 mouseleave
、点击事件 click
往往只会执行一次,即便事件回调函数性能稍差也不会带来巨大的影响;而像页面滚动事件 scroll
、鼠标移动事件 mousemove
,它们是相对连续的,往往会在一个时间段反复被触发。如果事件回调的代码消耗性能较强,则直接会对页面的流畅性产生非常大的影响。
而且如果可以使用低频的事件实现相同的效果,就不要使用高频事件。例如:我们需要在鼠标移入某一区域时改变该区域的背景颜色,如果使用监听该区域的 mousemove
事件是同样可以实现这样的效果的,但它每一次鼠标移动都会触发它,而其实我们只需要mouseenter
事件一次执行该效果就可以了。类似地,我们还应分清诸如 mouseout
与 mouseleave
、mouseover
与 mousemove
的区别,选用更合适的事件以提升代码性能。
最后,如果某一个事件只用触发一次之后就不会再使用到,最好在该事件的回调函数中的结尾处进行 removeEventListener
,这既是为了性能考虑,也可以节省不必要的内存占用。
{ passive: true }
除了要更加注重这些高频事件的代码性能以外,我们还可以通过设置 EventListener
方法的第三个参数为 { passive: true }
,来更好地减少事件回调所要计算的代码。
{ passive: true }
的意思是让 EventListener
不再先阻止原来会发生的事件,即 preventDefault()
。
对于默认情况,浏览器是不知道 EventListener
所回调的事件中有没有包含 preventDefault()
,所以会先阻止默认事件执行,然后等回调事件执行完毕后再执行默认事件;但是大部分时候,我们其实并不会阻止默认事件,比如页面滚动,我们可能只是想获取滚动的参数,而不是禁止页面滚动。所以 2015 年 DOM 规范新增了 addEventListener
的第三个参数可以接收一个对象的规定,通过设置 { passive: true }
来使 preventDefault()
失效,使默认事件变得流畅。
这种优化一般只用于触摸、滚动事件,其他事件没有必要使用
「减少动画」与我们原本「增加动画」的目的其实是背道而驰的,这里体现的是「理想效果」与「视觉效果」的权衡。
本网页一开始增加了许多的动画效果,并在开发的时候暂时忽略了流畅性的要求,而在后期进行性能优化时,发现过多的高频动画本身(如只要鼠标移动,标题、背景图就会跟着反方向移动;页面滚动时,若干元素还会自己增加/减少自己的滚动距离)就是一个性能瓶颈。到了这种程度时,最好能够考虑优化它们的触发方式以减少它们的频率。如果仍然有性能问题,最后的方法就是舍弃它们,以保证用户的流畅体验,这也是在保证其他动画的视觉效果。
提到「网页性能」可能新手(包括我)第一个想到的是网页「运行」的性能,即网页浏览、动作响应时的流畅性,其实除了这方面,页面的加载与渲染速度同样是非常重要的指标。如果一个网页加载或者渲染得太久,用户的烦躁程度会大幅上升。对于这方面,我们可以从以下角度进行努力:
作为偏向于视觉设计的网页,CSS 相关的代码也不比 JavaScript 要少。不过更多的都是排版相关的基础问题,碰到了只要解决后总结好基本下次变得更加熟练。
在本项目中我第一次尝试 SCSS 语法来编写 CSS 代码,实际上非常容易上手,简单阅读完文档并做好完整的笔记后,编写 CSS 确实要方便许多。
动画方面,就是 transition
渐变效果与 CSS3 新出的 animation
属性相配合,多加使用后简单的 CSS 代码也能写出很棒的动画,即便是在普通的网站中,使用它们也能够在小细节上给用户好感。
不过,复杂动画使用 CSS3 可能就不一定合适了,这主要看是否属于 CSS 的强项领域中,否则遇到兼容性等问题还是没有办法的事情,毕竟其不是编程语言,具有一定的限制。
如果遇到了性能问题,CSS 黑科技 translate3d
和 will-change
作为最后的手段说不定能帮你一忙。
在现代浏览器中,遇到 3D 变换会启用 GPU 进行硬件加速,而 translate3d
是非常具有代表性的 3D 变换,所以在一些 2D 动画较多的地方使用它代替 translate
有可能能够对性能有所帮助。
will-change
则是在 CSS 代码中提前告知浏览器,某些属性可能会发生动画效果,促使浏览器积极地调用硬件加速去优化它,但这个属性是最后的手段,并不应该随便使用。
和 JS 一样的,触发频率过高的 CSS 动画(甚至只是通过伪类进行单纯的属性值改变)同样会引发性能问题,本站中鼠标与 42 个 ABOUT 文本元素原本都会产生 :hover
动画,但如果在页面滚动时鼠标不断触发该动画,在低端的设备上会容易产生卡顿问题。
我的解决方法是将 :hover
的触发条件改为了 :active
,这样鼠标移动+页面滚动就不会频繁触发该动画。
CSS3 新引入的 var 变量也是一个不错的玩意,常用的是将颜色定义为 CSS3 变量,便于使用 JS 替换该变量值,达到一键更换主题配色的效果,无需到处更改各种元素的颜色属性值。
页面的反色效果使用的是 fix-blend-mode: exclusion
实现的,这属性很酷,我很喜欢,点名表扬一下。
还有
filter
也是可以很酷的属性,但在本页面中没有什么使用(用了drop-shadow
),有视觉效果需求的话filter
属性是非常值得了解的对象。
作为一门标记语言,HTML 是每个程序员的基本功了。
Emmet 是一种提供自动补全的语法。举个简单的例子,我们可以输入 !
,然后输入Tab键,即可自动补全以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body></body>
</html>
再比如:
table>.row>.elem+.elem
按下tab键,我们可以得到:
<table>
<tr class="row">
<td class="elem"></td>
<td class="elem"></td>
</tr>
</table>
如果对 Emmet 语法有兴趣,可以看看这篇我写的 Emmet 笔记
语义化是 HTML5 的重点之一,这部分我也是一边学习、一边通过别人的优秀代码中了解到不同的语义化标签,<section>
、<header>
、<nav>
等常用标签就不介绍了(HTML5 结构元素介绍 一文可以通过实例帮助区分这些标签的作用),我还了解到下面几个标签:
<main>
<time>
<figure>
挺有意思,这不仅是增加了机器可读性,这些语义化标签更会让我觉得自己的代码非常的漂亮(误)
移动端适配的要诀就是:删得越多,需要适配的东西就越少(x)
说到适配,基本都是围绕着「自适应布局」和「响应式页面」两个概念来进行,毕竟重新开发一个页面专门用于移动端的成本相对而言是比较高的。
自适应布局,一般而言是使用 Flex
弹性布局与 Grid
栅格布局来实现,它们在尺寸的变化上具有连贯性,可以随着页面的尺寸变化通过压缩空白间距、自动换行等方式发生连续的排版变化。但是自适应是有极限的,从 PC 端到手机端这种尺寸与比例的巨大变化,一般而言「响应式设计」更加切合该问题。
响应式界面借助的是 CSS 的媒体查询特性,对不同的媒体以及屏幕尺寸应用不同的 CSS 样式。这个功能很强大,很多适配都是这么做的,某些不要的元素可以 display: none
隐藏掉,又可以把某些只在手机端的元素 display
出来。缺点就是它是阶段性的、离散的,需要设置多个断点来适配多种不同的尺寸。
所以这两个技术相辅相成,才能实现较好的单份页面多终端适配。
光有排版适配是不行的,还需要调整元素与文本的尺寸。常见的 rem
布局原本是个不错的主意,但在选择的时候我纠结地决定使用 vh
与 vw
来实现,媒体查询时则用 em
来调整字体大小,只能说各有所长。因为这方面经验不足,我也不确定使用 rem
方案会不会有更好的适配效果。
补充:
vh
单位在移动端的浏览器中存在问题。因为大部分移动端浏览器的标题栏是可以随着滚动的行为进行收起或者展开的,这导致了页面的一些遮挡。vh
是不变的值,但他会比我们期望的值还要大一点,很容易出现排版问题。建议如果需要在移动端浏览器中布局的话,尽量避免使用vh
,可以使用 js 获取并设置样式。(我已经被坑了)
坦白说,一开始适配都是用的 chrome 浏览器模拟手机端进行的,这导致我写了不少代码之后,等到网站上线服务器了,在手机上才发现我添加的动画与效果实在太多,导致移动端性能捉襟见肘。
于是乎只好包含泪水送走那些代码,在移动端禁用一些 js 脚本,甚至连 My Works 里我很喜欢的 CSS3 飞行员动画也要禁止了,页面访问才变得流畅起来。所以我只好在郁闷中开玩笑地总结道:「把发生性能问题的东西禁用掉就没有性能问题了。」
在移动端中,即使使用 transform 做动画也是非常消耗性能的,所以要尽量节约着使用
还有一些零碎的配置,顺嘴提一下:
一开始是从服务器中获取的,结果中文字体动辄 10MB
的大小严重影响了页面的加载访问,且单单使用英文字体也要考虑版权问题。
没经验的我一开始是打算尽量猜测用户电脑自带的字体种类,按在我页面中的实际显示效果排个序作为我的 font-family
。后来想起伟大的 GoogleFonts,非常简单易用地挑选到了我想要的字体,而且不用担心版权问题,点赞 👍
后续:GoogleFonts 虽说在中国也有了 CDN 站点加速,但是我发现有些时候获取字体资源的访问速度真的不算快,查了一下了解到 https://fonts.loli.net/ 可以反代理 GoogleFonts,免费公益速度又快,非常感人,好用 👍
阿里的 IconFonts 也是类似的,提供海量的图标,甚至给我用作为光标样式,很好用 👍
图片先压缩是基本操作,在损失较小的画质的情况下大幅加快加载速度是值得的。
不过在图片资源部署的问题上,我一开始出于偷懒,将图片放在了 sm.ms 上然后从网页中引用它。后来发现这好像是不被该图床所允许的,而且偶尔访问速度不够快,于是又移回了我的服务器中,起码我服务器这点流量而言对于获取一点图片资源还是足够稳定的。
服务器相关的东西都是是阿里云服务一条龙,机子选用的阿里云的学生机,域名也就顺便在阿里上买了,还挺便宜,然后阿里有个帮忙备案的功能,10 天批了下来,挺方便的。
https 协议是 http + SSL,如果只使用 http 协议,浏览器会给用户提示此网页不安全,而 SSL 证书是需要获取的。一开始我以为所有 SSL 证书都是要收费的,瞟了一眼一年收费一千多元可把我吓到了,心想算了算了 http 协议凑合着用。
后来转念一想发现不少普通的个人网站也是有 https 加密访问的,总不能大家都那么有钱叭,于是一搜果然有免费 SSL 证书可以申请(为这些厂商点赞 👍)。
然后就在准备按着教程去搞 Let's Scrypt 的 SSL 证书时,又想到了我的服务器装了宝塔面板,这种事情说不定在宝塔面板上有一键认证,结果发现真的有,只需要一个邮箱即可(给宝塔面板也点个赞 👍)。
之于网站流量分析用的是谷歌家的 Google Analytics,目前还没怎么使用,等有空了再摸摸看嘿嘿。
这第二部分倒回来稍微介绍一下主观性很强的本站的设计思路。
Tips: 整体设计以效果的多样性为主要目的,实验意味较浓
文章配图不够齐全之处,望读者亲自访问网页进行体验
主题色是页面视觉占比最高的颜色,它由背景图所决定。由于第一版配色选用的背景图片为红色系,故简单配了一个#882233
作为较暗的红色为主题色。
辅助色是在页面中烘托主题色的颜色,它的视觉占比一般仅次于主题色,用于平衡单主题色带来的视觉疲劳。在这里选用浅白色是因为页面为暗色主题的原因,使用浅白色作为全局的文本颜色非常合适。为了避免颜色过于复杂,图形化的标题颜色与光标颜色也使用文本颜色以统一视觉效果。
点缀色是相对主题色而言较为亮眼的高饱和度颜色,起到点睛的作用。在这里选用了与红色互补的青色,以加强视觉冲击效果,同时配合交互时发生的反色效果,可以起到呼应的作用。
注:一开始原本并没有想好点缀色,直到某天刷手机忽然看到一个角色,当时就拍脑袋嚷嚷着青配红可以有 😂
暗色主题算是 2019~2020 年的设计趋势之一。
以前我们只能在设计与编程类软件能看到暗色主题风格,这大多是出于暗色减少界面带来的创作注意力影响、提高对暗部细节的感知度。
而随着手机的流行,许多手机 app 也细心地推出「夜间模式」,这是出于用户在夜间浏览手机应用时能够减少屏幕过亮对眼睛造成的损害。
但「暗色主题」相比于「夜间模式」并不完全相同,因为「暗色主题」并没有便于夜间浏览的硬性要求,因此在主色为暗色的情况下仍然可以选择高明度的颜色作为配色,且配色思路与亮色主题并不相同,一般能够给出相比于亮色主题更酷更专业的感觉。
色块 / 扁平感是我对于内心某种设计要素比较模糊的称呼,大概是几年前「卡片化」、「扁平化」的类似体现。注重强调块状的单色区域,相比于颜色复杂的图案而言更加简洁干净。在实际实现中,采用的是「粗线条」、「粗体文字」、「单色简单几何图形」的方式来达到相关的理念。
阴影这里指的对应的是代码中的 shadow
样式,它是亮色主题常用的划分区域的缓和手段。弥散投影非常能够提升亮色主题的区域的质感,他能弱化区域的边界感,提升卡片感。
但是阴影效果在暗色主题中往往并不明显,只能起到一点辅助作用(上面的右图)。而如果将 shadow
设置为亮色,则变成光晕效果,给人一种物体正在发光的感觉(上面的左图文字与粗线条)。
透明化是提升画面信息的一种手段,在该页面实现中,将除了标题区域以外的区域罩上了一层暗色透明蒙版,避免背景图片影响文字阅读的同时保留背景细节,提升画面的信息量。
但是,「透明化」实际上与前面提到的「扁平化」(减少元素的信息量)有较大的不相容性,所以理论上这两种要素应该有所取舍更为合适。
反色也是提供视觉效果、保留页面信息的方法之一。因为元素之间常常会发生遮挡,被遮挡的元素会损失一定的信息内容,使用类似于透明的反色效果,能够保留信息的形状属性,但也会干扰信息的色彩属性。本站于光标样式上采用了反色技巧,因为光标是用户和页面交互的重要手段,操纵光标与不同的元素相作用会产生不同的视觉效果,提高用户的交互兴趣。
页面滚动是浏览网页非常常见的事件,一般的桌面浏览器都不会提供平滑滚动的效果,这主要是为了提高页面滚动的响应速度,因为毕竟不是所有人都喜欢缓动的滚动效果。在本站中,因为内容信息的获取并不是最重要的,为了体现个性以及更好的适应动画的流畅感,故添加了一定的平滑滚动效果。
特殊的,对于底部版权信息的区域,做了一个「揭底」的效果,在页面的最末尾打破用户对于网页窗口的认知,让页面主体变成了类似于荧幕一样的东西,揭底之时才露出背后并未移动的白墙。
视差滚动是近年来比较流行的页面交互效果之一,通过滚动时不同元素的滚动距离不同,让人感觉滚动距离更长的元素离我们更近,滚动距离更短的元素离我们更远,从而增加页面的空间感。
但是由于页面内容越来越多,性能较差的电脑与浏览器反而可能会产生卡顿,这点比较麻烦。
视觉提示与反馈是交互的重点。所谓交互,即需有用户的输入,也要有反馈这些输入的输出;或者通过输出提示,来引导用户的输入行为。本站中把这个重任交给了光标进行引导,通过样式的变化、大小放缩来进行相应的提示与反馈。
例子:
透视和视差类似,也是增加页面空间感的手段。近年来不同的设计领域都开始出现三维空间的要素,当然是因为三维效果跳脱于所处的二维空间,提供了多一个维度的视觉感受。本站将作品展示部分添加了相关的透视效果,通过鼠标与作品的相对位置对作品进行三维空间上的旋转,以凸显逼真的空间感。
大字号可以表现出不同于「需要为用户提供足量的信息的信息密集型网站」的气质,从视觉惯性上进行冲击,强调文字的存在性。在本站的实现中,还有着配合粗体标题字体来实现色块视觉效果的功能。
当然,如果使用不当,会给人一种变成老人机的大字模式的感觉,这方面英文作为排版设计常用字体非常有优势(单字母相比汉字更加符号化而非象形化),所以本站也使用了不少英文(装饰意义居多)。
大小对比是营造视觉落差非常常见的手法。顾名思义,拒绝暧昧的相近关系,让大的更大,小的更小,突出大小的对比,强调大与小的尺寸属性。
重复也是强调元素存在感的手法之一,装饰意味居多。在本站中有一串很长的 ABOUT,如果显示没有问题的话,可以看到它有空心和实心两种。实心的序列其实并不是随机的,而是满足质数的排列(作为一个彩蛋)。
暗示(hint)是对某特点与某效果之间的关系进行间接的绑定的手法,一般是用于大家普遍默认的关系。注意,非常浅显的图形标识或者文字标识当然不算暗示,信息量更小的特点被称为暗示更加合适。
例如看到包含单个词语或者图标的色块,这个特点会暗示我们这可能是一个按钮,而词语或者图标的具体意义才会告诉我们它的作用;又比如绿色常常用来暗示正确,红色往往被当作错误警告,这是颜色的暗示。
不过在本站中,我做的暗示不算是「大家普遍默认的关系」,而注重于统一整个页面的交互语言。
例如,光标与主题色的元素一定可以产生某种交互,触发由主题色渐变为点缀色的动画。
对于具有内外两层结构的光标,默认状态下内光标表示鼠标的实时坐标、外光标应用具有延迟的缓动动画来跟随内光标运动。当外光标和内光标同时表示为鼠标实时坐标位置时,其被暗示为按钮的一种,允许进行点击的操作。
这些非常识的暗示在传统意义上可能没有直接的价值,但是对于统一交互语言有着一定的帮助。用户一般不会注意到,但在潜意识中多少会产生一定的影响。
2024-02-17 08:00:00
封面摄于 2023.09.29,日本京都某不知名野庙
我发现,每到年末总是最忙的时段,想要在公历新年到来之前好好地写完一篇年记,确实是有点难度。于是我决定推迟到农历新年之前,这样也可以正好对上假期。
不过就目前来看,算上年记每年能更新的文章也都没法超过两篇,实在有点不太好意思说自己有在写博客。
其实在 2023 年也有尝试过选取一些选题,比如我对 AI 绘图的看法、聊聊角色关系的转变,但是写着总觉得自己的水平有限,只能做到堆砌观点而缺少深度的思考表述,于是便只好成为众多废稿之一。
那么,我在忙些什么呢?我开始反思自己。
首先感知的是那些日常之事。除了基础需要以外,还有这样一些事情同样在一直固定消费着我的时间:
它们看起来是枯燥的,在平凡的日子里总是不断地重复,但也是不可或缺的。意识到它们的存在,可以建立起对于事物的坐标系,更清醒地了解自己当下正在做什么,也就对于「日常」与「非日常」有了更深的感知。
排除掉上述日常以及杂事,还有印象的比较非日常的事情大概是这些:
总体算下来,虽然整的活也不算多,并没有把所有的空闲都好好利用起来,但也算有意识在做些「非日常」的事情。
另外回头看了下我王者荣耀的赛季历史,才发现我在 2022 年连续上了 4 个赛季的王者段位,而 2023 年则在春季打了王者 33 颗星之后,就没再怎么玩了。合理猜测正是从中我节约出了一笔不小的时间,使得 23 年的另外三个季度里有意义的事情频率变高了(大概)。
不过,蔚蓝档案我倒是几乎全年全勤,只是它的日常一般并不花多少时间,在这方面正好契合我对于游戏时长占比不多不少的期望。此外,这种一点一点积累的养成模式也很好地满足我对于积累的欲望。(什么电子盆栽)
头疼的是,对于琐碎的、没有明确截止日期的事情,总体而言完成度并没有那么理想。不提那些广泛的爱好们,举些更具体的例子:
对我来说,它们是有意义的,但当下总是缺乏下定决心去做的动力。常常用着看起来很有道理的理由,告诉自己有更紧急重要的事情去做,但实际上又把不少时间投入到所谓的「放松」上。况且有时也不一定真的有放松到,甚至还产生了一些焦虑。
当然了,因为享乐行为本身而反而产生焦虑完全是本末倒置的。不过,如何巧妙地化解这样的问题则值得去好好研究,找到适合自己的方法。如果能够让自己在做有意义的事情的过程中,同时持续保持积极正向的心态,那便是再好不过。
需要声明的是,我也并不喜欢事事都做完整的规划安排,多点弹性才符合自由的天性。事情越做越多可能未必是一件坏事,关键还是要有真正下定决心开始去做的自驱力,剩下的就只是做多做少的问题。不做白日梦,而做白日梦想家。
在 2023 年之前,我的思维体系里的许多关键词以及观点,都是通过自己的思考总结、以及零零散散内化他人观点拼凑出来的。而在某个瞬间,我忽然发现平时里在想的那些懵懂的东西,有很大一部分都可以归类为「哲学」这个概念,而在此之前我居然未曾察觉。
哲学、文学、社学科学,作为一名理工科生,在过去,我也确实不够重视对于这些知识的主动接触和学习。在了解相关知识的过程中,我逐渐发现先前懵懵懂懂的抽象问题,其实早已被各种优秀的人思考总结过了,甚至建构出了完整的理论体系;许多作品亦是围绕相关的思想进行创作,如果事先具备相关的知识,能够更好地理解作者所想要表达的观点。
不过也没有后悔接触得太迟,因为很多思想都需要曾经有过类似的体验与思考才能够深刻地理解,太早接触反而只会不知所云。有些时候,学习新的思想本质上也是在使其与自己现有的思想做相互印证,从而在细节上完善属于自己的思维体系。
并且,不是所有思想都适合每个人。有时某些观点或许充满道理,但倘若无法在自己身上重复地验证的话,就说明它可能并不适合自己。在这个学习的过程中,还是需要自己去挑选出最合适自己的一些方法论并加以总结,才能够很好地融入自己的思维模式中去。
当然了,虽然总是在强调学习与思考,但我们更需要注意避免的是名为「过度思考」的陷阱,因为思考总让我们不得不直面内心最深处的问题,但往往不是所有问题都能够得到解答。过度思考,使我们断开与现实的连接,陷入幻想中的世界。
所谓的心理问题,在很多时候都是源于自己对于事物的认知陷入了一种局限。如果正处于倒向诸如「虚无主义」的消极情绪的过程中,通过学习相关的理论知识,倒是可以正确认识并找到属于自己的解决问题的方法。
虽然在这些过程中可能并不舒坦,但最后多少可以获得更加沉稳的内心世界。在面对「人生的意义」之类的宏大命题时,也或许能够看得稍微清楚那么一点点。
……
题外话,《进击的巨人》动画历经十一年连载终于在今年完结。动画在剧情上填补了漫画的部分缺失,在我心目中为这个作品画下了最完美的句号。而作者谏山创老师在结尾,就曾用存在主义思想对抗虚无,借着阿尔敏之口,表达了他作为文学创作者的其中一部分思想:
那天傍晚,我们三个人朝着山丘上的那颗树为终点赛跑,
提议要赛跑的艾伦一说完就冲了出去,三笠故意落后跑在艾伦后面,我果然又是最后一名。
但是,那一天的风非常暖和,光是跑着就觉得很舒服。
看着枯叶漫天飞舞,那时我不知为何突然觉得……我说不定就是为了在这里跟他们一起赛跑,才出生在这个世界上的。
下雨天在家里看书的时候,看松鼠吃掉我给的树果的时候,和大家一起逛市场的时候,我都会这么想。
这些平凡无奇的时刻,对我来说非常重要。
——最终话「朝着那座山丘上的树」
很多时候,我们都生活得太过「连续」了,连续得完全停不下来思考,坐在高速行驶的汽车上向着某个目的地疾驰,在这个过程中逐渐忘记了自己,甚至忘记了目的,变得只专注于「疾驰」本身。
就好像多年前我从未想过主动去散步——「要做的事情可太多了,哪有这么多奢侈的时间可以浪费?这是中老年人才喜欢的养生环节。」
但近年来我也开始逐渐理解:散步本身确实没有直接的意义,但在这个过程中,我们短暂逃离了世俗意义的纠缠,得以有机会去关注各种事物的存在。
打扫、洗碗、洗晒衣物等琐事亦是如此,正是这些平凡的日常才构筑起了生活的绝大多数。借助这些事物的存在,我们得以确认自己的存在。
倘若经常意识不到这些事物存在的点点滴滴,当我们失去所谓宏大的目标之时,也就容易陷入至虚无之中。
虽然这个系列的标题叫「年记」,但似乎前两年的年记更多的只是对于跨年当下的心境的记录,今年才在此基础上,加入了一点对于当年所做过的事情的总结。
为了让年记更加专注于对当年日常生活的记录,我决定后续可以把比较独立的观点与思考类的文字,另外拆成单独的博客,这样能够使每篇博客的主题不至于过分松散。(博客的数量也不至于太少)
而关于日常生活记录的部分,将应该补充更多的细节。因为这些不涉及大量的思考整理,所以写起来应该会轻松一些,不至于一写就是一两个月。
实际上,随着这篇年记一起写的还有「思考」的消失一文,正因为上述的考虑,最后将其从年记中摘出去;而至于文中关于「哲学学习的感悟」的内容则比较散漫,于是还是放在本文之中。
总得来说,这个系列于我而言还是挺有意义的——适时的总结与回顾,有助于保持清醒。日常思考的过程中,经常会产生大量零碎模糊的观点,趁着这个机会得以把它们挑挑拣拣组织到一起,虽然是需要花上不少的功夫,但整理清晰后的秩序感也令人感到内心安稳。
「世界上只有一种真正的英雄主义,那就是在认清生活的真相后依然热爱生活。」
回顾完 2023 年,虽然在这过程中时常迷茫、对一些事物愈发地感到失望,也曾陷入过虚无,甚至至今也还未认清生活的真相,但也总有些微小而确定的收获存在,让我仍然保持对于生活的向往。