支持导航滚动的Extjs实现

导航滚动组件的形式参考百度百科:

http://baike.baidu.com/subview/837441/10940762.htm



 

它由导航条和可滚动内容两者构成。

它具有以下3个特点:

1. 导航条本身是位置固定(Dock)或浮动的;

2. 点击导航条button,内容区会滚动到相应位置;

3. 在内容区滚动,导航条会自动active当前位置对应的button;

 

此形式的JQuery实现有很多,比如这个Scrollit.js

http://www.bytemuse.com/scrollIt.js/

 

相比较常见的标签页(tab)形式,两者都能快速地定位内容,导航滚动具备的最大优势是:

它可以更好地适应不同的屏幕分辨率,更高的屏幕高度,每屏可浏览更多内容。

 

ExtJS官方本身没有提供这种内容组织形式,但是在ExtJS提供的丰富的基础组件和开放的扩展机制上,实现这种形式并不难。我的实现思路如下:

1. 采用tabbar作为导航条;

2.调用函数scrollIntoView实现点击按钮,滚动到指定位置;

3.响应内容区的scroll事件,active对应的导航按钮;

 

实现效果如下:


点击按钮“Panel2”滚动



 

鼠标滚动内容区,滚动到显示Panel3的位置,导航按钮自动active“Panel3”


代码如下:

/**
 * Demonstrates usage of navbar.
 */
Ext.define('DCApp.view.navpanel', {
    extend: 'Ext.panel.Panel',
    xtype: 'navpanel',
    layout: {
        type: 'fit',
        pack: 'start',
        align: 'stretch'
    },
    
    bodyPadding: 10,
 	width: 500,
    height: 400,

    items: [
        {
            id:'panel0',
        	listeners: {
    		  render: function(p){
    			p = p.getEl();
    			var me= this.up();
    			me.h0=p.getHeight();
    		    p.on('scroll', function(e, t){
    		    	//console.log(t.scrollTop +"   "+ t.clientHeight);
    		    	me.onscroll(t.scrollTop,t.clientHeight);
    		    }, p);
    		  }
    		},
        	title: 'Panel 0',
            flex: 2,
            frame: true,
            xtype: 'container',
            layout: 'anchor',
            style: {
                overflow: 'auto'
            },
            defaults: {
                frame: true,
                bodyPadding: 10
            },
            items: [
                    {
                        title: 'Panel 1',
                        flex: 1,
                        margin: '0 0 10 0',
                        cls:'nav_pos',
                        height:300,
                        html: 'height: 300'
                    },
                    {
                        title: 'Panel 2',
                        height: 100,
                        margin: '0 0 10 0',
                        cls:'nav_pos',
                        height:400,
                        html: 'height: 400'
                    },
                    {
                        title: 'Panel 3',
                        flex: 2,
                        cls:'nav_pos',
                        height:500,
                        html: 'height: 500'
                    }
                ]
            }
    ],
    onscroll:function(top,h0){
    	var items_navpos=this.items_navpos;
    	var offset=0;
    	//var h0 = this.h0;
    	for(var i=0; i<items_navpos.length; i++){
    		var item_navpos=items_navpos[i];
    		var h = item_navpos.getHeight();
    		//header落在移动窗口之内,或移动窗口在 两个offset之间都算
    		if((offset>=top && (offset<= (top+h0)))
    				|| (top>=offset && (top+h0) <= offset+h ))
    			break;
    		offset+=h;    		
    	}
    	this.nav(this.btns_dock.getAt(i));
    },
    nav:function(item,e){
    	if(this.item_last){
    		if(this.item_last==item)
    			return false;
    		this.item_last.removeCls('x-tab-active');
    	}
    	var pnav = item.pnav;
    	if(e){
        	pnav.getEl().scrollIntoView(pnav.up().getEl(),false,true);     
    	}else{
    		item.addCls('x-tab-active');
    	}
    	this.item_last=item;
    },
    afterRender: function(ct, position) {
    	var items_dock=[];
    	var items_navpos=this.query('[cls=nav_pos]');
    	var me = this;
    	for(var i=0; i<items_navpos.length; i++){
    		var item_navpos=items_navpos[i];
    		var item_dock = {
    			closable:false,
    			text:item_navpos.title,
    			pnav:item_navpos,
    			handler:me.nav,
    			scope: me
    		};
    		items_dock[items_dock.length]=item_dock;
    	}
    	this.items_navpos=items_navpos;
    	this.btns_dock = this.addDocked([{
	        xtype: 'tabbar',
	        dock: 'top',
	        id:'tbar0',
	        activeItem:1,
	        items: items_dock
	    }])[0].items;
    	this.nav(this.btns_dock.getAt(0));
    	this.callParent();
    },
    initComponent: function(){
    	this.callParent();
    }
});

Ext.application({
    name : 'Fiddle',

    launch : function() {
        //Ext.Msg.alert('Fiddle', 'Welcome to Sencha Fiddle!');
        Ext.create('widget.navpanel', {renderTo:Ext.getBody()});
    }
});

 
 在线Demo

https://fiddle.sencha.com/#fiddle/kfr
 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值