Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Created March 19, 2015 11:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save barneycarroll/22d01a4de895be187433 to your computer and use it in GitHub Desktop.
Save barneycarroll/22d01a4de895be187433 to your computer and use it in GitHub Desktop.
Occlusion culling in Mithril
function occluder(){
var fresh = true;
var item = 40;
var offset = 0;
var scroller = window;
var viewport = 0;
return {
scroller : function scrollerConfig( el, init, context ){
if( arguments.length < 2 || !init || fresh ){
window.removeEventListener( 'scroll', update, false );
scroller = el;
scroller.addEventListener( 'scroll', update, false );
context.onunload = function teardown(){
scroller.removeEventListener( 'scroll', update, false );
};
fresh = false;
update();
}
},
view : function mapView( list, template ){
var total = ( item * list.length ) || 0;
var modulo = ( offset % item ) * -1;
var start = Math.floor( offset / item );
var end = Math.floor( ( viewport / item ) + start + 2 );
var occlusion = list.slice( start, end );
return m( '', {
config : containerConfig,
style : {
height : total + 'px',
position : 'relative',
top : modulo + 'px'
}
}, m( '', {
style : {
config : getItemSize,
position : 'relative',
top : offset + 'px'
}
}, occlusion.map( template )
)
);
}
};
function containerConfig( el, init, context ){
if( !init && !fresh ){
window.addEventListener( 'scroll', update, false );
window.addEventListener( 'resize', update, false );
context.onunload = function teardown(){
window.removeEventListener( 'scroll', update, false );
window.removeEventListener( 'resize', update, false );
};
}
}
function getItemSize( el, init ){
if( !init ) item = el.firstChild.getBoundingClientRect().height;
}
function update( event ){
offset = scroller.scrollTop || 0;
viewport = scroller.offsetHeight || 0;
m.redraw();
}
}
@barneycarroll
Copy link
Author

m.module( document.body, {
    controller : function(){
        this.occluder = occluder();
        this.users    = m.request( { method : 'GET', url : '/users' } );
    },
    view : function( ctrl ){
        return m( '.page', {
            config : ctrl.occluder.scroller
        },
            m( '.fixedHeader', 'Hello' ),
            m( 'ul.content', ctrl.occluder.view( users(), function( user, index ){
                return m( 'li', [
                    m( 'span.index', index ),
                    m( 'a', { href : user.profile }, user.fullName )
                ] );
            } ) )
        )
    }
} );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment