scrollIntoView 实现「建议收藏」

scrollIntoView 实现「建议收藏」1.应用场景: 相信大家都曾经遇到过要将屏幕的某一部分滚到到用户视窗里,例如聊天信息的自动滚屏等,这个有不少解决方案: 1.聊天面板的scrolltop=scrollheight2.消息最后加一个element,然后element.scrollIntoView但是如果想要任一容器中间的一个元素,滚到该容器的视窗显示部分…

大家好,又见面了,我是你们的朋友全栈君。

1.应用场景:

 

相信大家都曾经遇到过要将屏幕的某一部分滚到到用户视窗里,例如 聊天信息的自动滚屏 等,这个有不少解决方案:

 

1.聊天面板的scrolltop=scrollheight

2.消息最后加一个element,然后element.scrollIntoView


但是如果想要 任一容器中间的一个元素,滚到该容器的视窗显示部分 应该应用不广泛。


2.Extjs API:


extjs的核心 Element 包含了这一方法。


scrollIntoView[Mixed container ] , [Boolean hscroll ]  ) : Ext.Element

Scrolls this element into view within the passed container.
Scrolls this element into view within the passed container.

Parameters:
  • container : Mixed
    (optional) The container element to scroll (defaults to document.body). Should be a string (id), dom node, or Ext.Element.
  • hscroll : Boolean
    (optional) False to disable horizontal scroll (defaults to true)

Returns:

  • Ext.Element
    this


这个函数的效果就是将父区域内的子区域显示到父区域的视窗部分。

 

 

3.Extjs 实现详解:

 

 

子区域在父区域内大概分为三种关系:


1.子区域在父区域视窗底部,且子区域没有父区域视窗高,

scrollIntoView 实现「建议收藏」


2.子区域比父区域视窗高

scrollIntoView 实现「建议收藏」

 

3.子区域顶部在父区域视窗顶部以上,且子区域没有父区域视窗高

scrollIntoView 实现「建议收藏」

 

 

对于这三种情况,要分别处理,其中 二和三最终的处理方式一样的。

 

那么现在就可以分析extjs处理滚动高度部分的代码了:

 

scrollIntoView : function(container, hscroll){
        var c = Ext.getDom(container) || Ext.getBody().dom;
        var el = this.dom;
				
//子区域渲染后在屏幕上和父区域视窗的左边距和上边距,
//为负时,表示子区域有上部分在父区域视窗上面,如第三种情况
        var o = this.getOffsetsTo(c),
        
        //分别计算子区域相对父区域结点的坐标(不是父区域视窗)
            l = o[0] + c.scrollLeft,
            t = o[1] + c.scrollTop,
            b = t+el.offsetHeight,
            r = l+el.offsetWidth;

        var ch = c.clientHeight;
        var ct = parseInt(c.scrollTop, 10);
        var cl = parseInt(c.scrollLeft, 10);
        var cb = ct + ch;
        var cr = cl + c.clientWidth;


        //二三种情况,如果子区域比父区域视窗还高或者,
        //区域有上部分在父区域视窗上面,就把子区域顶部和父区域视窗顶部对齐
        //注意:子区域比父区域视窗还高,优先显示子区域顶部部分内容,比较合理。
        if(el.offsetHeight > ch || t < ct){
        
        	c.scrollTop = t;
        	
        	
        }else 
        
        //第一种情况,如果子区域在父区域视窗下面,或者有下部分在父区域视窗下面,
        //且子区域没有父区域视窗高,就把子区域底部和父区域视窗底部对齐
        if(b > cb){
            c.scrollTop = b-ch;
        }
}

宽度调整同理。

 

 

4.总结:

 

scrollIntoView 实现「建议收藏」

 

关键为初始根据scrollTop以及offsetTo得到元素和容器内容上边界的固定差值,之后只需赋值 scrollTop,在容器内容条上滑动 容器显示区域 到一定位置使得元素和容器的上(下)边对其即可。

 

PS1: scrollIntoView 原生解释

 


将一个元素滚动到视窗,如果参数为true则元素会被滚动到视窗的顶部,否则他会被滚动到视窗底部,默认为true。


当该方法被调用时,作用元素必须引起调用者的注意。


在读屏器中,可使得当前的播放位置重置到作用元素的开头。


在可视化的用户代理中,如果参数为false,用户代理必须滚动窗体使得元素的顶部和底部在当前视窗都可见,并且底部和视窗的底部对齐。如果当前视窗不能完全显示元素,或者元素参数被忽略则默认为true,那么用户代理应该将元素的顶部和视窗的顶部排列,如果当前页面可以完全显示在视窗中,那么用户代理不应该进行任何滚动。可视化用户代理应该同样进一步进行水平滚动使得该元素能够引起用户注意。


非可视化用户代理可以忽略调用参数,或者以合适的媒体特性来区别对待。

 

模拟原生 scrollView 的 kissy 实现

 

 

/**
         * Makes elem visible in the container
         * @refer http://www.w3.org/TR/2009/WD-html5-20090423/editing.html#scrollIntoView
         *        http://www.sencha.com/deploy/dev/docs/source/Element.scroll-more.html#scrollIntoView
         *        http://yiminghe.iteye.com/blog/390732
         */
        scrollIntoView: function(elem, container, top, hscroll) {
            if (!(elem = S.get(elem)) || !elem[OWNER_DOCUMENT]) return;

            container = S.get(container);
            hscroll = hscroll === undefined ? true : !!hscroll;
            top = top === undefined ? true : !!top;

            // default current window,use native for scrollIntoView(elem, top)
            if (!container || container === win) {
                // 注意:
                // 1. Opera 不支持 top 参数
                // 2. 当 container 已经在视窗中时,也会重新定位
                return elem.scrollIntoView(top);
            }
            //document 归一化到 window
            if (container.nodeType && container.nodeType == 9) {
                container = getWin(container);
            }
            //support iframe's win    
            var notWin = !('scrollTo' in container && container[DOCUMENT]),
                elemOffset = DOM.offset(elem),
                cl = notWin ? container.scrollLeft : DOM.scrollLeft(container),
                ct = notWin ? container.scrollTop : DOM.scrollTop(container),
                //import! viewport should has
                containerOffset = notWin ? DOM.offset(container) : {left:cl,top:ct},
                diff = {
                    left:elemOffset.left - containerOffset.left  ,
                    top:elemOffset.top - containerOffset.top
                },
                eh = elem.offsetHeight,
                ew = elem.offsetWidth,
                //left
                l = diff.left + cl,
                //top
                t = diff.top + ct,
                b = t + elem.offsetHeight,
                r = l + elem.offsetWidth,
                ch = notWin ? container.clientHeight : DOM.viewportHeight(container),
                cw = notWin ? container.clientWidth : DOM.viewportWidth(container),
                //container视窗下doc高度下限
                cb = ct + ch,
                //container视窗下doc右边限
                cr = cl + cw;
            //used if container is window
            var wl = 0,wt = 0;
            if (eh > ch || top) {
                if (notWin)
                    container.scrollTop = t;
                else
                    wt = t;
            } else {
                if (notWin)
                    container.scrollTop = t - (ch - eh);
                else
                    wt = t - (ch - eh);
            }

            if (ew > cw || l < cl) {
                if (notWin)
                    container.scrollLeft = l;
                else
                    wl = l;
            } else if (r > cr) {
                if (notWin)
                    container.scrollLeft = l;
                else
                    wl = l;
            }
            if (!notWin && (wl || wt)) {
                container.scrollTo(wl, wt);
            }

        }
    });

 


PS2:原生使用注意


使用原生的 element.scrollIntoView() 时,会同时使 element 所在容器也会进行 scrollIntoView 操作,特别当 elment 为处于 iframe 中的一个元素,则当调用 element.scrollIntoView() ,不但使得 iframe 内的窗口滚动到 element 所在处,同时也会使主窗口滚动到 iframe 处,某些场景这也许不是我们所期望的(编辑器工具栏操作编辑区iframe内元素),这时模拟实现的scrollIntoView就有用武之地了,调用:

new Node(element).scrollIntoView(iframe.contentWindow);

 
使得只滚动 iframe 内的窗口,而保持主窗口不变。


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148687.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Linux下编写GT911触摸驱动

    Linux下编写GT911触摸驱动问题一:资源获取Gt911数据手册在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911Datasheet_121120(海威思.pdf问题二:需要准备哪些知识1.能够修改设备树2.能够编写字符设备驱动3.能够在linux下编写中断程序4.能够在linux下编写IIC收发程序5.了解input子系统6.移植tslib(用于校准,测试触摸屏)gt911硬件连接(韦老师的板子):可以看到gt911只

    2022年6月16日
    311
  • kubeadm 常用命令

    kubeadm 常用命令kubeadm 概述 Kubeadm 是一个工具 它提供了 kubeadminit 以及 kubeadmjoin 这两个命令作为快速创建 kubernetes 集群的最佳实践 安装官方参考 kuadmin 安装任务 kubeadminit 启动引导一个 Kubernetes 主节点 kubeadmjoin 启动引导一个 Kubernetes 工作节点并且将其加入到集群 kubeadmupgra 更新 Kubernetes 集群到新版本 kubeadmconfi 如果你使用 kube

    2025年9月17日
    3
  • Xml加载出错

    Xml加载出错在加载xml文件的时候xmlDoc.LoadXML()可能会出现这样的错误XmlException: Text node cannot appear in this state.Line1,position1. Mono.Xml2.XmlTextReader.ReadText(BooleannotWhitespace) Mono.Xml2.XmlTextReader.ReadConte…

    2022年7月26日
    40
  • C语言基础知识入门(大全)「建议收藏」

    C语言基础知识入门(大全)「建议收藏」一.C语言入门C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。C语言不但执行效率高而且可移植性好,可以用来开发应用软件、驱动、操作系统等。C语言也是其它众多高级语言的鼻祖语言,所以说学习C语言是进入编程世界的必修课!更多详细进阶教程等你领取!可以关注公众号“C和C加加”回复“ZXC”即可免费获取!二.C语言的具体结构简单来说,一个C程序就是由若干头文件和函数组成。 #include<stdio.h>就是一条预处理命..

    2022年6月7日
    28
  • oracle 优化or 更换in、exists、union all几个字眼,测试没有问题!

    oracle 优化or 更换in、exists、union all几个字眼,测试没有问题!

    2022年1月1日
    54
  • 论物联网与大数据、云计算、工业物联网、区块链「建议收藏」

    论物联网与大数据、云计算、工业物联网、区块链「建议收藏」论物联网与大数据、云计算、工业物联网、区块链我们当今的时代飞速发展,物联网、大数据、云计算这些名词在我们的生活中出现的越来越频繁,看似高大上的三者其实却和我们的生活息息相关。本篇文章就物联网、大数据以及云计算对三者之间的关系以及应用进行描述。工业物联网和区块链也进行了介绍。(一)物联网(1)什么是物联网物联网(InternetofThings,简称IoT)是指通过各种信息传感器、射频识别技术、全球定位系统、红外感应器、激光扫描器等各种装置与技术,实时采集任何需要监控、连接、互动的物体或过程,采

    2022年9月26日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号