or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animatable.mdanimation.mddraggable.mdeasings.mdengine.mdindex.mdscope.mdscroll.mdsvg.mdtext.mdtimeline.mdtimer.mdutilities.mdwaapi.md
tile.json

scope.mddocs/

Scope

Scoped animation context for managing animation lifecycles, cleanup, and shared configuration across related animations.

Capabilities

createScope Function

Create scoped animation context for organized animation management and automatic cleanup.

/**
 * Create scoped animation context
 * @param parameters - Scope configuration
 * @returns Scope instance
 */
function createScope(parameters?: ScopeParams): Scope;

Usage Example:

import { createScope } from "animejs/scope";

const scope = createScope({
  root: ".component",
  defaults: {
    duration: 1000,
    ease: "outQuad",
  },
});

// All animations inherit defaults and are tracked in scope
scope.animate(".box", { x: 100 });

// Cleanup all animations at once
scope.revert();

Scope Class

Scoped context for managing animations, shared configuration, and lifecycle control.

/**
 * Scope class for animation context management
 */
class Scope {
  // ===== Properties =====

  /**
   * Default parameters applied to all animations in scope
   * Shared configuration for consistent behavior
   */
  defaults: DefaultsParams;

  /**
   * Root element for scoped queries
   * All selectors are resolved within this root
   */
  root: Document | DOMTarget;

  /**
   * Named methods added to scope
   * Custom reusable animation functions
   */
  methods: Record<string, ScopeMethod>;

  /**
   * Data storage for scope
   * Store any custom data associated with scope
   */
  data: Record<string, any>;

  /**
   * Media query match results
   * Automatic tracking of responsive breakpoints
   */
  matches: Record<string, boolean>;

  // ===== Methods =====

  /**
   * Add named method to scope
   * Create reusable animation function within scope
   * @param methodName - Name for the method
   * @param method - Method implementation
   * @returns Scope instance for chaining
   */
  add(methodName: string, method: ScopeMethod): Scope;

  /**
   * Add constructor function to scope
   * Execute immediately and on scope refresh
   * @param constructor - Function to execute
   * @returns Scope instance for chaining
   */
  add(constructor: () => Tickable | Revertible | void): Scope;

  /**
   * Add one-time constructor function
   * Execute once, don't re-run on refresh
   * @param constructor - Function to execute once
   * @returns Scope instance for chaining
   */
  addOnce(constructor: () => Tickable | Revertible | void): Scope;

  /**
   * Execute callback in scope context
   * Runs immediately with scope context
   * @param callback - Function to execute
   * @returns Scope instance for chaining
   */
  execute(callback: (scope: Scope) => void): Scope;

  /**
   * Keep animation time synced in scope
   * Wrap constructor to maintain timing across refreshes
   * @param callback - Constructor that returns Tickable
   * @returns Scope instance for chaining
   */
  keepTime(callback: () => Tickable): Scope;

  /**
   * Refresh scope
   * Re-runs constructors and updates all animations
   * @returns Scope instance for chaining
   */
  refresh(): Scope;

  /**
   * Revert all scope animations and cleanup
   * Removes all animations, timers, and event listeners
   * @returns Scope instance for chaining
   */
  revert(): Scope;
}

Usage Examples:

import { createScope, animate } from "animejs";

// Create scope with defaults
const scope = createScope({
  root: ".app",
  defaults: {
    duration: 800,
    ease: "outQuad",
  },
});

// Animations inherit defaults
const anim1 = scope.animate(".header", {
  opacity: [0, 1],
  // Automatically uses duration: 800, ease: 'outQuad'
});

const anim2 = scope.animate(".content", {
  translateY: [50, 0],
  duration: 1200, // Override default
});

// Cleanup all animations in scope
scope.revert();

Shared Default Parameters

Configure defaults applied to all animations in scope:

const scope = createScope({
  defaults: {
    duration: 1000,
    ease: "outCubic",
    composition: "blend",
  },
});

// These inherit defaults
scope.animate(".box1", { x: 100 });
scope.animate(".box2", { y: 100 });
scope.animate(".box3", {
  rotate: 360,
  duration: 2000, // Override default
});

Scoped Root Element

Scope all queries to specific root element:

// Scope to component
const componentScope = createScope({
  root: ".my-component",
});

// Queries relative to root
componentScope.animate(".header", { opacity: 1 }); // Finds .my-component .header
componentScope.animate(".footer", { y: 0 }); // Finds .my-component .footer

// Multiple components with same structure
document.querySelectorAll(".card").forEach((card) => {
  const scope = createScope({ root: card });

  scope.animate(".title", { opacity: [0, 1] });
  scope.animate(".content", { y: [20, 0] });
});

Named Methods

Add reusable animation methods to scope:

const scope = createScope({
  root: ".app",
});

// Add named method
scope.add("fadeIn", (targets, params) => {
  return scope.animate(targets, {
    opacity: [0, 1],
    translateY: [20, 0],
    ...params,
  });
});

scope.add("slideOut", (targets, params) => {
  return scope.animate(targets, {
    translateX: [0, 100],
    opacity: [1, 0],
    ...params,
  });
});

// Use named methods
scope.fadeIn(".box1");
scope.slideOut(".box2", { duration: 500 });

Constructor Functions

Add initialization functions that run with scope:

const scope = createScope({
  root: ".page",
});

// Add constructor - runs immediately and on refresh
scope.add(() => {
  // Setup animations
  scope.animate(".header", {
    opacity: [0, 1],
    translateY: [-50, 0],
  });

  scope.animate(".content", {
    opacity: [0, 1],
    delay: 300,
  });
});

// Add one-time constructor - runs once only
scope.addOnce(() => {
  console.log("Initializing scope");
  // One-time setup
});

// Refresh re-runs constructors (except addOnce)
scope.refresh();

Execute Callback in Scope

Run code with scope context:

const scope = createScope({
  root: ".container",
  defaults: { duration: 1000 },
});

scope.execute((s) => {
  // Access scope properties
  console.log(s.root);
  console.log(s.defaults);

  // Create animations in scope
  s.animate(".item1", { x: 100 });
  s.animate(".item2", { y: 100 });
});

Keep Time Synced

Maintain animation time across scope refreshes:

const scope = createScope();

scope.keepTime(() => {
  return animate(".box", {
    rotate: 360,
    duration: 5000,
    loop: true,
  });
});

// Animation continues from current time after refresh
scope.refresh();

Data Storage

Store custom data in scope:

const scope = createScope();

// Store data
scope.data.animationSpeed = "fast";
scope.data.isRevealed = false;
scope.data.currentStep = 1;

// Access data
if (scope.data.animationSpeed === "fast") {
  scope.defaults.duration = 500;
}

// Use in animations
scope.add(() => {
  scope.animate(".step", {
    opacity: scope.data.currentStep === 1 ? 1 : 0,
  });
});

Media Query Matching

Track responsive breakpoints in scope:

const scope = createScope({
  matches: {
    mobile: "(max-width: 768px)",
    tablet: "(min-width: 769px) and (max-width: 1024px)",
    desktop: "(min-width: 1025px)",
  },
});

// Access match results
if (scope.matches.mobile) {
  scope.animate(".menu", { translateX: ["-100%", 0] });
} else {
  scope.animate(".menu", { opacity: [0, 1] });
}

// Auto-updates on viewport changes
window.addEventListener("resize", () => {
  scope.refresh(); // Re-evaluates matches
});

Scope Lifecycle Management

Complete lifecycle control:

// Create scope
const scope = createScope({
  root: ".component",
  defaults: { duration: 1000 },
});

// Add animations
scope.add(() => {
  scope.animate(".element", { x: 100 });
});

// Refresh scope - re-runs constructors
scope.refresh();

// Cleanup all animations and revert
scope.revert();

Component Pattern

Use scopes for component-based animations:

class AnimatedComponent {
  private scope: Scope;

  constructor(element: HTMLElement) {
    this.scope = createScope({
      root: element,
      defaults: {
        duration: 600,
        ease: "outQuad",
      },
    });

    this.init();
  }

  private init() {
    this.scope.add("show", () => {
      return this.scope.animate(".content", {
        opacity: [0, 1],
        translateY: [20, 0],
      });
    });

    this.scope.add("hide", () => {
      return this.scope.animate(".content", {
        opacity: [1, 0],
        translateY: [0, -20],
      });
    });
  }

  show() {
    this.scope.show();
  }

  hide() {
    this.scope.hide();
  }

  destroy() {
    this.scope.revert();
  }

  update() {
    this.scope.refresh();
  }
}

// Usage
const component = new AnimatedComponent(document.querySelector(".card"));
component.show();

// Cleanup when done
component.destroy();

Multiple Scopes

Organize complex apps with multiple scopes:

// Header scope
const headerScope = createScope({
  root: ".header",
  defaults: { duration: 500 },
});

headerScope.add(() => {
  headerScope.animate(".logo", { opacity: [0, 1] });
  headerScope.animate(".nav", { translateY: [-20, 0] });
});

// Main content scope
const contentScope = createScope({
  root: ".main",
  defaults: { duration: 800 },
});

contentScope.add(() => {
  contentScope.animate(".article", { opacity: [0, 1] });
});

// Footer scope
const footerScope = createScope({
  root: ".footer",
  defaults: { duration: 600 },
});

// Cleanup all
function cleanup() {
  headerScope.revert();
  contentScope.revert();
  footerScope.revert();
}

Refresh on Route Change

Update animations on route changes:

const pageScope = createScope({
  root: ".page",
});

pageScope.add(() => {
  // Animations for current page state
  const page = pageScope.root.getAttribute("data-page");

  if (page === "home") {
    pageScope.animate(".hero", { scale: [0.8, 1] });
  } else if (page === "about") {
    pageScope.animate(".team", { opacity: [0, 1] });
  }
});

// On route change
router.on("change", () => {
  pageScope.refresh(); // Re-evaluate animations
});

Conditional Animations

Create responsive animations based on conditions:

const scope = createScope({
  root: ".feature",
  matches: {
    mobile: "(max-width: 768px)",
  },
});

scope.add(() => {
  if (scope.matches.mobile) {
    // Mobile animations
    scope.animate(".content", {
      translateY: [100, 0],
      duration: 400,
    });
  } else {
    // Desktop animations
    scope.animate(".content", {
      translateX: [-100, 0],
      scale: [0.9, 1],
      duration: 600,
    });
  }
});

// Refresh on resize
window.addEventListener("resize", () => {
  scope.refresh();
});

Types

/**
 * Scope configuration parameters
 */
interface ScopeParams {
  /** Default parameters for all animations in scope */
  defaults?: DefaultsParams;

  /** Root element for scoped queries */
  root?: string | Document | DOMTarget;

  /** Media query definitions for responsive behavior */
  matches?: Record<string, string>;

  /** Initial data storage */
  data?: Record<string, any>;
}

/**
 * Default parameters for animations
 */
interface DefaultsParams {
  /** Default duration */
  duration?: number;

  /** Default easing */
  ease?: EasingParam;

  /** Default composition mode */
  composition?: TweenComposition;

  /** Any other animation parameter */
  [key: string]: any;
}

/**
 * Scope method function type
 */
type ScopeMethod = (...args: any[]) => Tickable | Revertible | void;

/**
 * Revertible object with cleanup
 */
interface Revertible {
  revert(): void;
}

/**
 * DOM target type
 */
type DOMTarget = HTMLElement | SVGElement;

/**
 * Tickable animation or timer
 */
type Tickable = Timer | JSAnimation | Timeline;