`
yiminghe
  • 浏览: 1465586 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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.子区域在父区域视窗底部,且子区域没有父区域视窗高,


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

 

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

 

 

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

 

那么现在就可以分析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.总结:

 

 

关键为初始根据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 内的窗口,而保持主窗口不变。

  • 大小: 17.6 KB
  • 大小: 17.1 KB
  • 大小: 20.3 KB
  • 大小: 37 KB
分享到:
评论
1 楼 hope-hyn 2013-08-29  
赞一个,公司框架在用suggestframework的时候用到了scrollIntoView ,我的jsp界面比较长,当用suggestframework的时候向下向上,jsp就在最后,开始我还以为是up down的影响,屏蔽掉后没反映,仔细查了好久才发现是scrollIntoView 的原因,纠结了半天不知到如何解决.虽然现在还没有解决,但是相信用了模拟的scrollIntoView 会解决的.先谢谢啦

相关推荐

    前端项目-jquery-scrollintoview.zip

    jQuery ScrollIntoView插件应运而生,它提供了一个方便的方法来实现这一功能,使得开发者能够轻松控制页面元素的滚动展示。 首先,我们来了解一下jQuery。jQuery是一款广泛应用于Web开发的JavaScript库,它的出现极...

    如果需要,请滚动到视图:Element.scrollIntoView填充“需要”和“平滑”之类的内容

    此后,CSS工作组决定在Element.scrollIntoView实现其功能,方法是使用scrollMode: "if-needed"选项。 因此,对该库进行了重写,以实现该规范,而不是即将弃用的规范。 安装 yarn add scroll-into-view-if-needed ...

    jquery.scrollIntoView:滚动元素进入视图时触发回调

    在压缩包文件名"jquery.scrollIntoView-master"中,我们可以推测这是该功能的一个完整实现,可能包含了源代码、示例和文档。查看这个项目的源码可以帮助我们更好地理解和使用这个功能,也可以根据自己的需求进行定制...

    提交页面的定位–scrollIntoView的用法

    - 需要考虑不同浏览器对`scrollIntoView`的实现可能存在的差异,以确保代码的跨浏览器兼容性。 - 当元素不在当前视口内时,`scrollIntoView`才生效;如果元素已经在视口内,则不会进行滚动。 总结来说,`...

    在vue项目实现一个ctrl+f的搜索功能

    在Vue项目中实现一个类似`Ctrl+F`的搜索功能,主要涉及到前端的文本搜索、DOM操作和事件监听。以下是对实现这一功能的详细步骤和关键知识点的解释: 1. **需求分析**: - 首先明确需求,通常一个搜索功能包括一个...

    js实现目录定位正文

    虽然`scrollIntoView()`和`behavior: 'smooth'`在现代浏览器中广泛支持,但为了确保在旧版本的浏览器中也能正常工作,可能需要添加一些兼容性处理代码,如使用polyfill库或手动实现平滑滚动的动画效果。 5. **性能...

    css3动画效果

    JavaScript动画通常通过改变元素的样式属性来实现,例如使用`requestAnimationFrame`方法来平滑地更新屏幕。这种方式可以实现更精确的控制,如响应用户交互或同步多个动画。 4. **Wow.js 动画库** Wow.js是一个...

    vue+Element实现搜索关键字高亮功能

    在介绍如何使用Vue.js结合Element UI框架实现搜索关键字高亮显示之前,我们首先要了解几个基础知识点。 Vue.js是一个用于构建用户界面的渐进式JavaScript框架。它将数据和视图分离,通过数据的双向绑定来驱动视图的...

    返回页面顶部,顶端

    在网页开发中,实现“返回顶部”的方法多种多样,可以使用JavaScript、jQuery或者其他前端库来完成。下面我们将详细探讨几种常见的实现方式。 ### 1. HTML与CSS基础 首先,你需要在HTML中创建一个元素,通常是`&lt;a&gt;`...

    Vue列表如何实现滚动到指定位置样式改变效果

    然后需要获取到列表对应的id值,直接使用 document.getElementById(it).scrollIntoView(); 具体实现: 列表:使用vue的v-for指令 ,这里的id值使用的是遍历的索引值,外层是一个自定义滚动条组件。样式也是使用vue指

    大小2个ScrollView

    然而,为了实现“大小2个ScrollView”的需求,我们可以使用LinearLayout、RelativeLayout或者其他布局容器来组合两个ScrollView。 假设我们有两个大小不同的图片,一个大图和一个小图。大图需要全屏显示并可滚动,...

    【JavaScript源代码】vue实现锚点定位功能.docx

    - `jump(index)` 方法中,为了实现平滑滚动,避免使用可能不兼容的 `scrollIntoView` 方法,我们可以采用分步滚动的方式。将目标滚动距离分成多个小段,然后在一定时间间隔内逐次调整滚动位置,模拟平滑滚动效果。 ...

    原生JS实现的平滑返回顶部特效源码.zip

    2. `Element.scrollIntoView()`: 如果我们希望某个元素回到顶部,可以使用此方法,配合`{behavior: 'smooth'}`选项来实现平滑滚动。 ```javascript const topButton = document.getElementById('top-button'); ...

    详解Vue项目中实现锚点定位

    在给定文件内容中,提到了一种使用`scrollIntoView()`方法来实现锚点定位的解决方案。`scrollIntoView()`是一个标准的Web API,它允许元素滚动到浏览器窗口的可视区域内。在Vue中,可以在方法中调用该函数,将目标...

    外卖:实现类似锚点功能毕业设计—(包含完整源码可运行).zip

    这通常通过修改`window.scrollTo`方法或使用`Element.scrollIntoView`实现。 4. **CSS样式与布局**:为了让锚点功能正常工作,需要设置合适的CSS样式和布局。例如,每个锚点对应的部分需要有唯一的ID,以便...

    最简单的方法搞定键盘遮挡

    描述中的“源代码解决键盘遮挡”意味着我们将通过编写简单的代码片段来实现这个功能,而无需引入额外的库或者复杂的工具。这种方法的优势在于,它减少了项目的依赖性,使代码更加简洁、易于维护。此外,“思路清晰化...

    Vue监听滚动实现锚点定位(双向)示例

    在项目需求中需要实现一个滚轴联动锚点的功能 效果图如下: 功能代码demo如下: (item, key=index xss=removed xss=removed&gt; &lt;div style=width:100%;height:100%;font-size:30

    ScrollView横向自动滑动

    在Android开发中,ScrollView通常用于实现可滚动的布局,它允许用户查看超出屏幕尺寸的内容。当我们需要在水平方向上实现类似的功能,可以使用HorizontalScrollView。本篇将详细讲解如何实现"ScrollView横向自动滑动...

    react-native-scroll-into-view:将 ReactNative 视图滚动到可见屏幕中。 类似于 DOMElement.scrollIntoView() 浏览器函数

    类似于用于 Web 的DOMElement.scrollIntoView() ,但有一些额外功能。 yarn add react-native-scroll-into-view// ornpm install react-native-scroll-into-view --save没有本机代码:这个库与 Expo 管理的工作流程...

Global site tag (gtag.js) - Google Analytics