惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
J
Java Code Geeks
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
月光博客
月光博客
腾讯CDC
Engineering at Meta
Engineering at Meta
博客园 - Franky
Vercel News
Vercel News
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
GbyAI
GbyAI
B
Blog
Hugging Face - Blog
Hugging Face - Blog
T
Tailwind CSS Blog

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
小tips: 滚动容器尺寸变化子元素视觉上位置不变JS实现 « 张...
张鑫旭,zhangxinxu · 2018-02-02 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=7351
本文可全文转载,但需要保留原作者和出处。

一、先从需求说起

对于一个宽度不固定的滚动容器,如果里面内容已经滚动到了一定的高度,这个时候滚动容器的宽度发生变化,则里面内容的位置会进行重定位,一不留神就不知道刚才的位置是哪里了。

尤其是看小说这种非常考验眼力的场景。

例如下面的GIF截图演示:

位置发生明显变化

于是,就有需求。

当滚动容器尺寸发生变化的时候(如宽屏窄屏切换,或者默认尺寸变全屏时候),最上面元素位置要保持不变,这样视觉体验就很好。不会因为突然的尺寸变化而不知道刚才看到哪里了。

那么该如何实现呢?

需要借助JavaScript手动修正滚动位置。

二、滚动容器尺寸变化子元素视觉上位置不变的JS处理

我们先看实现后的截屏gif效果:

滚动位置特别处理后的gif截屏效果

您可以狠狠地点击这里:滚动容器尺寸变化时候最上方元素位置不变demo

滚动容器到合适位置,然后改变浏览器窗口尺寸,可以体验到微丝不动的非常友好的交互体验效果。

JS实现的原理

  1. 获得最靠近滚动容器上边缘的元素;
  2. 获得最靠近滚动容器上边缘的元素距离上边缘的距离;
  3. 当滚动容器尺寸改变后,获得之前最靠近上边缘元素现在距离上边缘的距离,根据前后的差值修正此时的scrollTop大小;

原理第一步是最难点,如何获得最靠近滚动容器上边缘的元素呢?

我这里使用的是document.elementsFromPoint方法,语法如下:

var elements = document.elementsFromPoint(x, y);

表示返回所有距离浏览器可视窗口x, y坐标的DOM元素集合。因此,elements是一个从最子元素开始,依次向上,一直到<body><html>元素的类数组集合。

在本例中,elements[0]就是我们需要的元素。

假设滚动容器元素的idbox,则使用JavaScript代码表示就是:

var box = document.getElementById('box');

// x就取滚动容器水平中心点
var x = box.getBoundingClientRect().left + box.clientWidth / 2;
// + 12为了让更靠下一点的元素作为边缘元素
var y = box.getBoundingClientRect().top + 12;
// target就是我们获取的最接近滚动容器上边缘的元素
var target = document.elementsFromPoint(x, y)[0];

然后target距离上边缘的距离也很好实现(容器scroll事件时候执行):

var offsetTop = target.getBoundingClientRect().top - box.getBoundingClientRect().top

最后,根据滚动后的边缘距离进行滚动修正(窗体resize事件时候执行):

var currentOffsetTop = box.getBoundingClientRect().top - target.getBoundingClientRect().top;
// 滚动修正,效果达成
box.scrollTop = box.scrollTop - currentOffsetTop - offsetTop;

更完整JS代码参见demo页面(就几十行),大家可以根据自己实际项目场景进行修改,这里不重复展示。

关于document.elementsFromPoint API的兼容性

根据MDN上的数据,document.elementsFromPoint IE10+才支持,而且需要ms私有前缀,因此,如果想要兼容IE浏览器,可以加一句:

if (!document.elementsFromPoint) {
    document.elementsFromPoint = document.msElementsFromPoint;
}

由于本文实例属于体验增强的功能,因此,就算浏览器不支持也无伤大雅,能够让90+%浏览器有更好体验已经很棒了,因此是可以放心大胆使用的一个技术案例。

IE浏览器下更多细节

在IE浏览器下测试,resize时候滚动内容有晃动,我猜测可能与边缘位置计算带小数有关,因此,offsetTop的计算都是取整的,如下示意:

var currentOffsetTop = Math.round(box.getBoundingClientRect().top) - Math.round(target.getBoundingClientRect().top);

体验果然好了很多。

另外,在Chrome等浏览器下,target的获取和偏移计算可以直接在window resize时候执行。但是IE浏览器不行,似乎IE浏览器先触发浏览器行为,再执行了resize事件,所以,综合下来,还是建议最上边缘元素获取放在scroll事件中处理。

三、结束语

一个JS体验优化实例,没什么其他好展开的。

感谢阅读!

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=7351

(本篇完)