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)
上一篇 2022年6月28日 下午8:46
下一篇 2022年6月28日 下午9:00


相关推荐

  • jdbc访问mysql(百度app下载)

     MySQL下载地址:http://dev.mysql.com/downloads/mysql/5.1.html#downloads 选择你对应的操作系统,然后选择这个系统下的第一个或者第二个,点击Pickamirror后即可下载 MySQL的JDBC驱动下载地址:http://dev.mysql.com/downloads/connector/在页面中选择你对应的开

    2022年4月10日
    37
  • 《Android平台开发之旅》学习笔记

    《Android平台开发之旅》学习笔记第三章:Android应用程序组件3.2Android应用程序组件Activity活动–形象大使Service服务–老黄牛BroadcastReceiver广播接收器–倾听者ContentProvider内容提供者3.3组件应用机制3.1.1组件之间的交互机制Intent(意向)组件实现组件之间的交互,马上要执行的动作3..1.2未决意意向Pending…

    2026年4月16日
    6
  • 2025最全Claude账号被封解决方案:8种有效方法恢复访问【实战指南】

    2025最全Claude账号被封解决方案:8种有效方法恢复访问【实战指南】

    2026年3月16日
    2
  • 字符串匹配的kmp算法_多字符串匹配

    字符串匹配的kmp算法_多字符串匹配一、背景  给定一个主串(以S代替)和模式串(以P代替),要求找出P在S中出现的位置,此即串的模式匹配问题。  Knuth-Morris-Pratt算法(简称KMP)是解决这一问题的常用算法之一,这个算法是由高德纳(DonaldErvinKnuth)和沃恩·普拉特在1974年构思,同年詹姆斯·H·莫里斯也独立地设计出该算法,最终三人于1977年联合发表。  在继…

    2022年8月21日
    10
  • 火山引擎推出Data Agent评测体系,并发布《2025数据智能体实践指南》

    火山引擎推出Data Agent评测体系,并发布《2025数据智能体实践指南》

    2026年3月15日
    2
  • 大话数据结构学习心得

    大话数据结构学习心得想重温一下数据结构和算法,选择了大话数据结构这本书。本书用趣味的方式介绍了数据结构起源、算法设计,线性表、栈与队列、串、树、图、查找、排序。对于当前用高级语言(java,c#,python等)开发的软件开发人员来说可能相关内容涉及不到,因为高级语言已经封装好了相关方法。但是了解了计算机内存存储、查找、排序等算法对于开发人员来说会有一个新的认识:例如如何优化方法提高存储速度、查询速度等。附:…

    2022年6月24日
    30

发表回复

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

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