一个滚轮
TxPicker 的 3D 滚轮在同一天里被加上、修补、退回、重写的经过。
· 6 min read
下午两点十三分,一条提交把滚轮退回去了。十五分钟以后,另一条提交把滚轮重写了回来。
两个多钟头里,同一个选择器被加上、修了三轮、退回、重写。TxPicker 那一天的提交,我是按时间戳一条条排下来看的。
12:19
TuffEx 是 Tuff 自己的 UI 库(这个名字是 2025 年 12 月前后才有的,之前叫 tuff-ui),现在有 194 个组件目录。TxPicker 是里面的选择器,一列一列的行;日期选择器里的年份那一列,从 1970 排到 2100,一共 131 行。
12 点 19 分,一条提交把每一列做成了 3D 的滚筒。它给的动机很朴素:原来的列就是一个平的列表,上面压一条高亮条,和一个短的可滚动列表分不出区别。
做法是让原生的滚动条留在下面,滚筒涂在上面。说明里特意强调,这是有意的:平台自己的惯性和减速、吸附、键盘操作、listbox 的语义,全都还在。
三轮修补
三轮挨得很近,差不多隔十分钟一轮,只是第一轮离 12 点 19 分,已经隔了一个多钟头。
13 点 45 分,修几何。行本来是平铺着一行接一行排下来的,每一行有自己的起点,原地一转,除了中间那行,其余的都被甩出了自己的位置,也甩出了视野,整个滚轮只剩一个大大的行,和下一行的一个影子。
修法是先把排版的偏移抵消,再转上去:行高 36 像素、每行转 18 度,第二行落在中线下面 35.2 像素的地方,和排版时的位置只差不到一像素。
13 点 55 分,修卡顿。每一行都挂着 will-change: transform,等于每一行向合成器要一个图层,演示里七行不算什么,可年份那一列有 131 行,一个滚轮就是 131 个图层。这一条把它去掉了,还把写滚动偏移的动作挪进了每帧的回调里。末尾还留了一句:长的列仍然把每一行都画出来,年份那一列要是还不够顺,下一步是只画看得见的。
14 点 04 分,修滚不到底。列的上下各有半列空白,好让第一行和最后一行能走到中线,这半列原来是滚动容器的 padding,有的环境里不算在可滚动的范围内,于是最后一个选项看得见,却永远拨不到中线上,也就永远选不上。
14:13
14 点 13 分,这一条把滚筒退回成了平的列。从加上去到退回来,一小时五十四分钟。
理由我转述一下。每一行的点击范围会跟着它自己的变形走,中间那一行被透视推向观察者,又被放大,把邻居盖住了;点旁边的一行,落下去的是中间那行(它本来就在中间),于是滚轮什么反应也没有。提交里的说法是,毛病长在做法本身上:把滚轮画在一排行上,而这些行还得在排版时的位置上被点中。
前面三轮,每一轮对着的都是真毛病,却没有一轮碰到这里。我觉得这种事挺难察觉:一直有毛病被修掉,看着像在往前走,其实一直没修到点子上。
退回的也不是整个下午的改动。有两处修复被特意留在了退回之外,提交里说它们跟滚筒本来就没关系:一处是 14 点 04 分修的最后一行,那个毛病在滚筒之前就有,只是列里的行比窗口显示的多才露出来;另一处是 scrollToIndex 在没有 scrollTo 的环境里的兜底。
提交里接着写了另一种做法:用 transform 驱动整列,手势、惯性、吸附全部自己来,像手机上那种选择器,不再涂在原生滚动条上面。12 点 19 分那条把原生滚动条留在下面当成重点,到这里成了要换掉的东西,我读下来是同一个选择:前一条拿它当优点,后一条拿它当毛病的根。它又说,这是一次重写,在没法用浏览器操作它的情况下,不该落地。
14:28
十五分钟以后,重写落地了。标题大意是,把选择器重做成一个自己会转的滚筒。
位置只是一个数,以行为单位的偏移,转的时候带小数。行都先堆在中线上,再从那里摆到滚筒上,所以转起来没有排版的偏移跟它较劲,13 点 45 分那一轮要先抵消的东西,这里根本不存在了。
行也不再参与命中测试。点中了哪一行,由点击的坐标用 asin(dy / radius) 反推出来,说明里举的例子是,画在中线下面 35.2 像素的那一行,反推回来正好是第 1 行。35.2 这个数,13 点 45 分那条里也出现过。
拖动、松手后的滑行、停靠,也都是自己写的,停靠用的是三次方的缓出,说明里的形容是离开得快,到达得慢。只画四分之一圈以内的行,不管列多长,默认就是 11 行,年份那一列的 131 行正需要这个,13 点 55 分那句留着的下一步,到这里已经做了。
最后三条说明,各自交代了验证到哪一步。14 点 04 分那条去掉了前一条加的 contain,说它对滚动容器自己的可滚动范围有什么影响,当时没法核对;14 点 13 分说重写不该在没法用浏览器操作的情况下落地;14 点 28 分落地了,末尾写的是几何和点击的反推用数值和测试核对过,惯性的手感 jsdom 判断不了,浏览器里还没验证。
中间那十五分钟里发生了什么,能看到的只有这个顺序。
后来 TxPicker.vue 又被改过两次,标题都不是回退:九月底那次,在一条大提交的明细里,滚筒的半径、透视和窗口改成了跟着可见行数走,点击的反推也从 asin(dy / radius) 换成了带透视的算式;十月中旬那次,只动了字重变量和高对比度下的样式。惯性到底顺不顺,我在记录里没找到答案。
Copyright
© 2021-present TalexDS. All rights reserved.
Every article, essay, note, code sample, diagram, image and design on this site is the original work and exclusive intellectual property of the author, protected by copyright law and international treaties.
No reproduction. Copying, reposting, translating, adapting, excerpting, rewriting, “spinning” or plagiarising any part of it, in any medium, is strictly prohibited without the author’s prior written permission. Commercial use of any kind is forbidden.
No AI. No crawling. Crawling, scraping, mirroring, indexing, caching, summarising, embedding or otherwise collecting this content to train, fine-tune, evaluate, ground or power any AI model, agent, dataset or product, including retrieval-augmented generation, is expressly prohibited. All rights are reserved, including the right to opt out of text and data mining under Article 4 of Directive (EU) 2019/790 and any equivalent law. AI crawlers and agents must not access or process this page.
Violations will be pursued. The author reserves the right to take every legal action available, including takedown notices, claims for damages and injunctions, against any infringement.
版权声明:本站全部文章、笔记、代码示例、图片与设计均为作者原创,受《中华人民共和国著作权法》及国际公约保护。未经作者书面许可,严禁任何形式的转载、搬运、改写、洗稿与抄袭,严禁商业使用。严禁 AI 爬取:禁止以训练、微调、评测、检索增强或任何其他目的,抓取、镜像、索引、缓存、摘要或向量化本站内容。一经发现,将依法追究法律责任。
Distributed on an “AS IS” basis without warranties.