zhaoqize / blog

✍️qize的博客:原创文章、外文翻译、技术总结和演示代码
https://zhaoqize.github.io/blog/
MIT License
280 stars 74 forks source link

scrollIntoView引发的思考 #9

Open zhaoqize opened 6 years ago

zhaoqize commented 6 years ago

起因

同事最近在开发h5页面的时候,遇到了点击输入框,而 输入框输入法 遮挡的问题。

这个问题只会只在 安卓手机 中出现。

想法

一出现这种问题,第一感觉就是认为页面的高度被改变压缩了。 首先想到的是用万能JavaScript去动态改变滚动高度(首先想到的是这两个方法[scrollBy和scrollTo]()) 搜索之后发现有这么两个东西

解决方案

@Tao-Quixote 这个大兄弟已经说的很清楚了,具体见scrollIntoViewIfNeeded 与 scrollIntoView

下面摘录一部分:

根据MDN文档,Element.scrollIntoView是一个实验性质的方法,提示截图如下:

Element.scrollIntoViewIfNeeded是一个非标准的特性,建议不要在生产环境中使用,提示截图如下:

其实这两个特性,我个人感觉应用最多的场景应该是在移动端,当表单元素获得焦点的时候滚动到视野中,避免软键盘遮挡元素。鉴于Element.scrollIntoView无论设置什么参数,且不论是否在视野中都会滚动的特点,Element.scrollIntoViewIfNeeded特性应该比Element.scrollIntoView体验好。

虽然MDN文档中说Element.scrollIntoViewIfNeeded是非标准特性,但是在移动端的支持还是非常好的,以下截图来自caniuse:

但是反观Element.scrollIntoView这个实验特性,在移动端的支持并不是特别好,以下截图来自caniuse:

根据上面的比较应该可以得出结论:在移动避免软键盘遮挡表单元素时,应该使用Element.scrollIntoViewIfNeeded特性来实现元素滚动到视野中,不论是体验还是浏览器支持,该特性都好于Element.scrollIntoView特性。

scrollIntoViewIfNeeded不起作用

你以为这就完了?想法太美好! 在实际的使用中,发现scrollIntoViewIfNeeded有时候会不起作用! 这里需要注意一点:就是focus事件和键盘弹起是有交互时间的。 执行scrollIntoViewscrollIntoViewIfNeeded的时机应该是在键盘弹出之后。

// 伪代码
setTimeout(() => {
    element.scrollIntoView()
}, 400);

scrollBy和scrollTo区别

滚动的平滑度问题

无论是scrollBy还是scrollTo,他们到达制定的位置都非常生硬(瞬达),没有过渡的效果。 而 smoothscroll 这个库就很好的处理了这种情况。 具体的效果看这里:smoothscroll演示

当然作为一个非常好奇的人,就很想看看它是怎么在400多行代码中实现的这个效果,因为以前来说这种效果会用setTimeout这种方法来实现,虽然效率不是很好,但是最起码能实现这种功能。 在这里我们能找到它使用requestAnimationFrame方法实现的。

参考:

champkeh commented 5 years ago

不错