https://codesandbox.io/s/material-progress-scale-qi4zd
可以点击 refresh 演示
最近写上传动画,用了 material-ui 的 progress,后来写上传组件文档的时候,用例里用 requestAnimationFrame 快速刷新进度条,发现进度条虽然 css 属性变了但是没有动
仔细观察发现了,是 translate 在开了过渡(transition)的情况下高速刷新就不会变化,把过渡关了就可以(当然实际场景中不可能刷新这么快,所以我也不可能关了过渡)
但是我脑子一抽试试用 scale 加上 transform-origin 来模拟 translate 呢,神奇的事情出现了
高速刷新状态下,它正常的动了,艹
为啥 scale 可以,但是 translate 不可以
用 setTimeout 模拟的时候发现在 120 左右这个延迟,很容易出现进度条抖动(回弹?),就是偶尔会出现进度条一下回去一点然后又前进呢,有办法解决吗(打印过进度 value 呢,是正常的)
1
myCupOfTea OP 好奇,难道没有人遇到过么
|
2
liuhuihao 2020-06-15 11:37:31 +08:00
用了 JS requestAnimationFrame 控制进度条进度,为什么还要使用 transition 过渡呢?
|
3
myCupOfTea OP @liuhuihao requestAnimationFrame 是用来 模拟高速刷新下的 upload 的
|
4
myCupOfTea OP @liuhuihao 控制进度条还是用的 transition + (translate/scale/width)
|
5
redbuck 2020-06-15 16:20:04 +08:00
```html
<style> .progress { border: 1px solid #e5e5e5; margin: 10px; overflow: hidden; } .inner { transition: transform 0.16s ease; height: 5px; background-color: yellowgreen; transform-origin: 0 50%; } </style> <div class="progress translate"> <div class="inner"></div> </div> <div class="progress scale"> <div class="inner"></div> </div> <script type="text/javascript"> const sleep = time => new Promise(resolve => setTimeout(resolve, time)); const frame = () => new Promise(resolve => requestAnimationFrame(resolve)) || sleep(16.7); const $ = s => document.querySelector(s); let progress = 0; const translate = $(".translate .inner"); const scale = $(".scale .inner"); function render() { translate.style.transform = `translateX(${progress - 100}%)`; scale.style.transform = `scaleX(${progress / 100})`; } async function update() { while (progress <= 100) { render(); // await frame() await sleep(50); progress++; } } update(); </script> ``` 帮你改个简单版的,排除多余变量. 问题依然存在. 但如果调整 sleep 的时间,可以发现时间越长,会稍微缓解一点. |
6
gaoryrt 2020-06-15 17:49:13 +08:00
有没有可能是这样的:
两个 fill 上的 transition 进行的都是 transform 默认值到当前值的补帧,而不是上一个值到当前值的补帧。 如果 dom 样式的更新时间足够大,transition duration 足够小,你应该能看到每次从头开始到当前值的动画,而非从上一个值到当前值的动画。 |
7
myCupOfTea OP @redbuck 是的,这个问题我和 material-ui 官方讨论了下,这种场景下关闭过渡就行了
|
8
myCupOfTea OP |
9
myCupOfTea OP @redbuck 其实我就是好奇 scale 也是加了过渡效果的,但是 scale 是可以的
本来这个场景其实基本不会出现来,没有上传会一直刷新这么快的 |
10
myCupOfTea OP 另外我测试发现 firefox 对 css var 支持不够好(该测试用例在 firefox 上闪烁的很厉害)
我把 css var 去了写了另外一个例子,防止有人觉得是 css var 的问题 https://codesandbox.io/s/material-progress-scale-not-css-var-zw5nt |
11
myCupOfTea OP |
12
gaoryrt 2020-06-15 18:21:24 +08:00
那应该是 scale 会有类似于视觉残留的效果?
或者说是 react 针对 style 里面的 calc 进行了优化导致了问题? |
13
myCupOfTea OP @gaoryrt 跟 react 没关系,我仔细观察过了。css 上的属性已经变了,说明已经从虚拟 dom 渲染到真实 dom 呢,上面也有个老哥写了原生的 js,应该就是 chromium 的问题
|