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 内的窗口,而保持主窗口不变。


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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(1)
blank

相关推荐

  • tkmybatis使用注解实现动态配置(feignclient注解使用)

    generator.properties:spring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://10.244.76.11:3306/esign?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBeha…

  • 爬虫415(UNsupported media type)问题解决

    爬虫415(UNsupported media type)问题解决爬虫遇到的问题:这两天做爬虫遇到些问题,我在这里总结一下,希望能够和大家分享,共同学习,共同进步。今天在我爬某个网站的时候,返回的结果是415,不支持的媒体类型(Unsupportedmediatype),当时遇到这个问题的时候,我有点蒙,什么是媒体,在这里先不管他什么是媒体,反正就是报错,但是能肯定的是415错误肯定是请求的问题。那么我就开始顺着我的爬虫经验挨个排除。1、我的IP有没有被封

  • treetable php,jQuery树型表格插件jQuery treetable

    treetable php,jQuery树型表格插件jQuery treetable插件描述:jQuery-treetable是一个jQuery插件。有了这个插件,你可以在一个HTML表格中显示树,即目录结构或嵌套列表。它使你的HTML文件干净的,展现出树状表格插件,你只需要每一行数据添加特定的数据属性。jQuery-treetable有了这个插件,你可以在一个HTML表格中显示树,即目录结构或嵌套列表。它使你的HTML文件干净的,展现出树状表格插件,你只需要每一行数据添加特定的…

  • matlab as(assert dominance)

    目录一.语法1.输入参数二.说明三.示例1.值在预期范围之内2.期望的数据类型3.预期的代码执行情况assert是条件为false时引发错误。一.语法assert(cond)assert(cond,msg)assert(cond,msg,A1,…,An)assert(cond,errID,msg)assert(cond,errID,msg,A1,…,An)1.输入参数cond-断言条件MATLAB表达式..

  • Tensor和NumPy相互转换「建议收藏」

    Tensor和NumPy相互转换我们很容易用numpy()和from_numpy()将Tensor和NumPy中的数组相互转换。但是需要注意的一点是:这两个函数所产生的Tensor和NumPy中的数组共享相同的内存(所以他们之间的转换很快),改变其中一个时另一个也会改变!1.Tensor转NumPya=torch.ones(6)b=a.numpy()print(a,b)a+=1print(a,b)b+=1print(a,b)tensor([1.,1.

  • Log4J 配置文件 指定类 properties

    Log4J 配置文件 指定类 properties

发表回复

您的电子邮箱地址不会被公开。

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