CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-better-scroll

High-performance mobile scrolling library with smooth scrolling, momentum, bounce effects, and extensive plugin support.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

events.mddocs/

Events

Comprehensive event system for tracking scroll state, user interactions, and lifecycle events. Better Scroll uses a custom event emitter pattern that allows you to listen for various scroll-related events throughout the interaction lifecycle.

Capabilities

Event Management Methods

on

Registers an event listener for the specified event type.

/**
 * Register an event listener
 * @param type - Event type name
 * @param fn - Event handler function
 * @param context - Context for 'this' in handler (default: BScroll instance)
 */
on(type: string, fn: Function, context?: any): void;

once

Registers a one-time event listener that automatically removes itself after first execution.

/**
 * Register a one-time event listener
 * @param type - Event type name  
 * @param fn - Event handler function
 * @param context - Context for 'this' in handler (default: BScroll instance)
 */
once(type: string, fn: Function, context?: any): void;

off

Removes an event listener for the specified event type.

/**
 * Remove an event listener
 * @param type - Event type name
 * @param fn - Event handler function to remove
 */
off(type: string, fn: Function): void;

Usage Examples:

import BScroll from "better-scroll";

const scroll = new BScroll('.wrapper');

// Register event listeners
scroll.on('scroll', handleScroll);
scroll.on('scrollEnd', handleScrollEnd);

// One-time listener
scroll.once('scrollStart', () => {
  console.log('First scroll started!');
});

// Remove listener
scroll.off('scroll', handleScroll);

function handleScroll(position) {
  console.log(`Scrolling to: ${position.x}, ${position.y}`);
}

function handleScrollEnd(position) {
  console.log(`Scroll ended at: ${position.x}, ${position.y}`);
}

Core Events

Scroll Lifecycle Events

scroll

Fired during scrolling with current position coordinates.

// Event: 'scroll'
// Payload: {x: number, y: number}
// Fired: During scrolling movement (frequency depends on probeType)

Usage:

scroll.on('scroll', (position) => {
  console.log(`Current position: ${position.x}, ${position.y}`);
  
  // Update scroll indicator
  updateScrollIndicator(position.y);
  
  // Parallax effects
  updateParallaxElements(position.y);
});

scrollStart

Fired when scrolling begins, before any movement occurs.

// Event: 'scrollStart'
// Payload: none
// Fired: When user starts scroll gesture

beforeScrollStart

Fired before scrolling starts, earliest in the scroll lifecycle.

// Event: 'beforeScrollStart'  
// Payload: none
// Fired: Before scroll gesture processing begins

scrollEnd

Fired when scrolling animation completes and comes to rest.

// Event: 'scrollEnd'
// Payload: {x: number, y: number}
// Fired: When scrolling animation finishes

Usage Example:

scroll.on('scrollStart', () => {
  // Hide UI elements during scroll
  hideFloatingButton();
});

scroll.on('scrollEnd', (position) => {
  // Show UI elements when scroll stops
  showFloatingButton();
  
  // Save scroll position
  saveScrollPosition(position);
  
  // Load more content if near bottom
  if (isNearBottom(position.y)) {
    loadMoreContent();
  }
});

Touch & Interaction Events

touchEnd

Fired when user lifts finger/releases mouse, regardless of whether scrolling will continue.

// Event: 'touchEnd'
// Payload: {x: number, y: number}
// Fired: On touch/mouse up event

flick

Fired when user performs a quick flick gesture.

// Event: 'flick'
// Payload: none
// Fired: When flick gesture is detected (based on flickLimitTime and flickLimitDistance)

scrollCancel

Fired when a scroll operation is canceled (e.g., when a click is detected instead of scroll).

// Event: 'scrollCancel'
// Payload: none  
// Fired: When scroll is canceled due to click detection

Usage Examples:

// Handle touch end for custom logic
scroll.on('touchEnd', (position) => {
  // Check if user scrolled past certain point
  if (position.y < -triggerThreshold) {
    triggerRefresh();
  }
});

// Handle flick gestures
scroll.on('flick', () => {
  // Custom flick behavior
  console.log('User performed a flick gesture');
});

System Events

refresh

Fired after the refresh() method completes recalculation.

// Event: 'refresh'
// Payload: none
// Fired: After refresh() method completes

destroy

Fired when the BScroll instance is destroyed.

// Event: 'destroy'
// Payload: none
// Fired: When destroy() method is called

Usage Examples:

scroll.on('refresh', () => {
  // Update custom UI after dimensions recalculated
  updateCustomScrollbar();
});

scroll.on('destroy', () => {
  // Clean up custom resources
  cleanupCustomElements();
  removeCustomEventListeners();
});

Feature-Specific Events

Pull-to-Refresh Events

When pull-to-refresh is enabled, additional events are available:

// Event: 'pullingDown'
// Payload: none
// Fired: When pull-down threshold is reached
// Required: options.pullDownRefresh = true

// Event: 'pullingUp' 
// Payload: none
// Fired: When pull-up threshold is reached  
// Required: options.pullUpLoad = true

Usage:

const scroll = new BScroll('.wrapper', {
  pullDownRefresh: {
    threshold: 50,
    stop: 20
  },
  pullUpLoad: {
    threshold: 50
  }
});

scroll.on('pullingDown', () => {
  // Show loading indicator and refresh data
  showRefreshLoader();
  fetchNewData().then(() => {
    scroll.finishPullDown();
  });
});

scroll.on('pullingUp', () => {
  // Load more data
  showLoadMoreIndicator();
  fetchMoreData().then(() => {
    scroll.finishPullUp();
  });
});

Event Timing & Probe Types

The frequency of scroll events depends on the probeType option:

interface ProbeTypeConfiguration {
  probeType: 0 | 1 | 2 | 3;
}

// probeType: 0 - No scroll events during animation
// probeType: 1 - Non-real-time scroll events (debounced)
// probeType: 2 - Real-time scroll events during momentum only
// probeType: 3 - Real-time scroll events always (including animations)

Usage Examples:

// For basic scroll position tracking
const scroll = new BScroll('.wrapper', {
  probeType: 1
});

// For smooth scroll indicators  
const scroll = new BScroll('.wrapper', {
  probeType: 2
});

// For real-time parallax effects
const scroll = new BScroll('.wrapper', {
  probeType: 3
});

Event-Driven Patterns

Scroll Position Tracking

class ScrollTracker {
  constructor(scrollInstance) {
    this.scroll = scrollInstance;
    this.setupEventListeners();
  }
  
  setupEventListeners() {
    this.scroll.on('scroll', this.updatePosition.bind(this));
    this.scroll.on('scrollEnd', this.savePosition.bind(this));
  }
  
  updatePosition(pos) {
    // Update scroll indicator
    const percentage = Math.abs(pos.y) / Math.abs(this.scroll.maxScrollY);
    this.updateScrollbar(percentage);
  }
  
  savePosition(pos) {
    // Persist scroll position
    localStorage.setItem('scrollPosition', JSON.stringify(pos));
  }
}

Infinite Scroll Implementation

class InfiniteScroll {
  constructor(scrollInstance, threshold = 100) {
    this.scroll = scrollInstance;
    this.threshold = threshold;
    this.loading = false;
    
    this.scroll.on('scroll', this.checkLoadMore.bind(this));
  }
  
  checkLoadMore(pos) {
    if (this.loading) return;
    
    const bottom = Math.abs(pos.y);
    const maxScroll = Math.abs(this.scroll.maxScrollY);
    
    if (bottom + this.threshold >= maxScroll) {
      this.loadMore();
    }
  }
  
  async loadMore() {
    this.loading = true;
    try {
      await this.fetchMoreData();
      this.scroll.refresh(); // Recalculate boundaries
    } finally {
      this.loading = false;
    }
  }
}

Custom Animation Triggers

const scroll = new BScroll('.wrapper', {
  probeType: 3
});

scroll.on('scroll', (pos) => {
  // Parallax background
  const parallaxElement = document.querySelector('.parallax-bg');
  const parallaxSpeed = 0.5;
  const translateY = pos.y * parallaxSpeed;
  parallaxElement.style.transform = `translateY(${translateY}px)`;
  
  // Fade header based on scroll
  const header = document.querySelector('.header');
  const opacity = Math.max(0, 1 - Math.abs(pos.y) / 200);
  header.style.opacity = opacity;
});

docs

core-scrolling.md

events.md

features.md

index.md

tile.json