or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

behavior-system.mdcontrollers.mdgraph-management.mdindex.mditem-management.mdshape-system.mdutilities.md
tile.json

behavior-system.mddocs/

Behavior System

Interaction behavior system allowing registration of custom behaviors and event handling for graph interactions. Behaviors provide reusable interaction patterns that can be combined and configured to create complex user experiences.

Capabilities

Behavior Registration

Register custom behaviors that can be applied to graphs for interaction handling.

/**
 * Register custom behavior for graph interactions
 * @param type - Behavior type name
 * @param behavior - Behavior implementation object
 */
function registerBehavior(type: string, behavior: BehaviorOption): void;

Usage Example:

import { registerBehavior } from "@antv/g6-core";

// Register custom hover behavior
registerBehavior('custom-hover', {
  getEvents() {
    return {
      'node:mouseenter': 'onNodeMouseEnter',
      'node:mouseleave': 'onNodeMouseLeave',
      'edge:mouseenter': 'onEdgeMouseEnter',
      'edge:mouseleave': 'onEdgeMouseLeave'
    };
  },
  
  onNodeMouseEnter(e) {
    const item = e.item;
    this.graph.setItemState(item, 'hover', true);
  },
  
  onNodeMouseLeave(e) {
    const item = e.item;
    this.graph.setItemState(item, 'hover', false);
  },
  
  onEdgeMouseEnter(e) {
    const item = e.item;
    this.graph.setItemState(item, 'hover', true);
  },
  
  onEdgeMouseLeave(e) {
    const item = e.item;
    this.graph.setItemState(item, 'hover', false);
  }
});

// Use behavior in graph modes
const graph = new MyGraph({
  modes: {
    default: ['custom-hover', 'drag-canvas', 'zoom-canvas']
  }
});

Behavior Interface

Complete interface for implementing custom behaviors with lifecycle hooks and event management.

/**
 * Behavior implementation interface
 */
interface BehaviorOption {
  /**
   * Define event to method mappings (required)
   * @returns Object mapping G6 events to method names
   */
  getEvents(): { [key in G6Event]?: string };
  
  /**
   * Get default configuration for behavior (optional)
   * @returns Default configuration object
   */
  getDefaultCfg?(): object;
  
  /**
   * Determine if behavior should begin (optional)
   * @param e - Graph event object
   * @returns True if behavior should start
   */
  shouldBegin?(e?: IG6GraphEvent): boolean;
  
  /**
   * Determine if behavior should update during execution (optional)
   * @param e - Graph event object
   * @returns True if behavior should continue updating
   */
  shouldUpdate?(e?: IG6GraphEvent): boolean;
  
  /**
   * Determine if behavior should end (optional)
   * @param e - Graph event object
   * @returns True if behavior should end
   */
  shouldEnd?(e?: IG6GraphEvent): boolean;
  
  /**
   * Bind behavior to graph (optional)
   * @param graph - Graph instance
   */
  bind?(graph: IAbstractGraph): void;
  
  /**
   * Unbind behavior from graph (optional)
   * @param graph - Graph instance
   */
  unbind?(graph: IAbstractGraph): void;
  
  // Custom event handler methods
  [key: string]: any;
}

Graph Events

Comprehensive enumeration of all available G6 events for behavior event mapping.

/**
 * Complete enumeration of G6 events
 */
enum G6Event {
  // Mouse events
  CLICK = 'click',
  DBLCLICK = 'dblclick',
  MOUSEDOWN = 'mousedown',
  MOUSEUP = 'mouseup',
  MOUSEMOVE = 'mousemove',
  MOUSEENTER = 'mouseenter',
  MOUSELEAVE = 'mouseleave',
  MOUSEOVER = 'mouseover',
  MOUSEOUT = 'mouseout',
  CONTEXTMENU = 'contextmenu',
  
  // Touch events
  TOUCHSTART = 'touchstart',
  TOUCHMOVE = 'touchmove',
  TOUCHEND = 'touchend',
  
  // Drag events
  DRAGSTART = 'dragstart',
  DRAG = 'drag',
  DRAGEND = 'dragend',
  DRAGENTER = 'dragenter',
  DRAGLEAVE = 'dragleave',
  DRAGOVER = 'dragover',
  DROP = 'drop',
  
  // Node events
  NODE_CLICK = 'node:click',
  NODE_DBLCLICK = 'node:dblclick',
  NODE_MOUSEDOWN = 'node:mousedown',
  NODE_MOUSEUP = 'node:mouseup',
  NODE_MOUSEMOVE = 'node:mousemove',
  NODE_MOUSEENTER = 'node:mouseenter',
  NODE_MOUSELEAVE = 'node:mouseleave',
  NODE_MOUSEOVER = 'node:mouseover',
  NODE_MOUSEOUT = 'node:mouseout',
  NODE_CONTEXTMENU = 'node:contextmenu',
  NODE_DRAGSTART = 'node:dragstart',
  NODE_DRAG = 'node:drag',
  NODE_DRAGEND = 'node:dragend',
  NODE_DRAGENTER = 'node:dragenter',
  NODE_DRAGLEAVE = 'node:dragleave',
  NODE_DRAGOVER = 'node:dragover',
  NODE_DROP = 'node:drop',
  
  // Edge events
  EDGE_CLICK = 'edge:click',
  EDGE_DBLCLICK = 'edge:dblclick',
  EDGE_MOUSEDOWN = 'edge:mousedown',
  EDGE_MOUSEUP = 'edge:mouseup',
  EDGE_MOUSEMOVE = 'edge:mousemove',
  EDGE_MOUSEENTER = 'edge:mouseenter',
  EDGE_MOUSELEAVE = 'edge:mouseleave',
  EDGE_MOUSEOVER = 'edge:mouseover',
  EDGE_MOUSEOUT = 'edge:mouseout',
  EDGE_CONTEXTMENU = 'edge:contextmenu',
  
  // Combo events
  COMBO_CLICK = 'combo:click',
  COMBO_DBLCLICK = 'combo:dblclick',
  COMBO_MOUSEDOWN = 'combo:mousedown',
  COMBO_MOUSEUP = 'combo:mouseup',
  COMBO_MOUSEMOVE = 'combo:mousemove',
  COMBO_MOUSEENTER = 'combo:mouseenter',
  COMBO_MOUSELEAVE = 'combo:mouseleave',
  COMBO_MOUSEOVER = 'combo:mouseover',
  COMBO_MOUSEOUT = 'combo:mouseout',
  COMBO_CONTEXTMENU = 'combo:contextmenu',
  COMBO_DRAGSTART = 'combo:dragstart',
  COMBO_DRAG = 'combo:drag',
  COMBO_DRAGEND = 'combo:dragend',
  COMBO_DRAGENTER = 'combo:dragenter',
  COMBO_DRAGLEAVE = 'combo:dragleave',
  COMBO_DRAGOVER = 'combo:dragover',
  COMBO_DROP = 'combo:drop',
  
  // Canvas events
  CANVAS_CLICK = 'canvas:click',
  CANVAS_DBLCLICK = 'canvas:dblclick',
  CANVAS_MOUSEDOWN = 'canvas:mousedown',
  CANVAS_MOUSEUP = 'canvas:mouseup',
  CANVAS_MOUSEMOVE = 'canvas:mousemove',
  CANVAS_MOUSEENTER = 'canvas:mouseenter',
  CANVAS_MOUSELEAVE = 'canvas:mouseleave',
  CANVAS_CONTEXTMENU = 'canvas:contextmenu',
  CANVAS_DRAGSTART = 'canvas:dragstart',
  CANVAS_DRAG = 'canvas:drag',
  CANVAS_DRAGEND = 'canvas:dragend',
  
  // Timing events
  BEFORERENDER = 'beforerender',
  AFTERRENDER = 'afterrender',
  BEFOREPAINT = 'beforepaint',
  AFTERPAINT = 'afterpaint',
  BEFOREADDITEM = 'beforeadditem',
  AFTERADDITEM = 'afteradditem',
  BEFOREREMOVEITEM = 'beforeremoveitem',
  AFTERREMOVEITEM = 'afterremoveitem',
  BEFOREUPDATEITEM = 'beforeupdateitem',
  AFTERUPDATEITEM = 'afterupdateitem',
  BEFOREITEMVISIBILITYCHANGE = 'beforeitemvisibilitychange',
  AFTERITEMVISIBILITYCHANGE = 'afteritemvisibilitychange',
  BEFOREITEMSTATECHANGE = 'beforeitemstatechange',
  AFTERITEMSTATECHANGE = 'afteritemstatechange',
  BEFOREITEMREFRESH = 'beforeitemrefresh',
  AFTERITEMREFRESH = 'afteritemrefresh',
  BEFORELAYOUT = 'beforelayout',
  AFTERLAYOUT = 'afterlayout',
  
  // Viewport events
  VIEWPORTCHANGE = 'viewportchange',
  BEFORECREATEEDGE = 'beforecreateedge',
  AFTERCREATEEDGE = 'aftercreateedge',
  
  // Keyboard events
  KEYDOWN = 'keydown',
  KEYUP = 'keyup',
  
  // Wheel event
  WHEEL = 'wheel'
}

Event Object Interface

Graph event object structure containing interaction details and target information.

/**
 * G6 graph event object interface
 */
interface IG6GraphEvent {
  item: Item | null;          // Target item (node, edge, combo)
  canvasX: number;           // Canvas X coordinate
  canvasY: number;           // Canvas Y coordinate
  clientX: number;           // Client X coordinate
  clientY: number;           // Client Y coordinate
  x: number;                 // Graph X coordinate
  y: number;                 // Graph Y coordinate
  wheelDelta: number;        // Mouse wheel delta
  detail: number;            // Event detail
  key?: string;              // Keyboard key
  target: IShapeBase;        // Target shape element
  originalEvent?: Event;     // Original DOM event
  bubbles?: boolean;         // Whether event bubbles
  defaultPrevented?: boolean; // Whether default prevented
  name: string;             // Event name
  timeStamp: number;        // Event timestamp
  type: string;             // Event type
}

G6GraphEvent Class

Extended event class for G6-specific event handling.

/**
 * G6 graph event class extending base GraphEvent
 */
class G6GraphEvent {
  public item: Item;
  public canvasX: number;
  public canvasY: number;
  public clientX: number;
  public clientY: number;
  public wheelDelta: number;
  public detail: number;
  public target: IShapeBase;
  
  /**
   * Create G6 graph event
   * @param type - Event type
   * @param event - Source event object
   */
  constructor(type: string, event: IG6GraphEvent);
}

Advanced Behavior Examples

Complete examples of common behavior patterns:

// Drag node behavior
registerBehavior('drag-node', {
  getDefaultCfg() {
    return {
      updateEdge: true,
      delegate: true,
      delegateStyle: {}
    };
  },
  
  getEvents() {
    return {
      'node:dragstart': 'onDragStart',
      'node:drag': 'onDrag',
      'node:dragend': 'onDragEnd'
    };
  },
  
  shouldBegin(e) {
    // Only allow dragging if node is not locked
    return !e.item.hasLocked();
  },
  
  onDragStart(e) {
    this.origin = { x: e.x, y: e.y };
    this.item = e.item;
    
    if (this.delegate) {
      // Create drag delegate
      this.createDelegate(e);
    }
  },
  
  onDrag(e) {
    if (!this.origin) return;
    
    const dx = e.x - this.origin.x;
    const dy = e.y - this.origin.y;
    
    if (this.delegate) {
      this.updateDelegate(e, dx, dy);
    } else {
      this.updateItem(e, dx, dy);
    }
  },
  
  onDragEnd(e) {
    if (!this.origin) return;
    
    const dx = e.x - this.origin.x;
    const dy = e.y - this.origin.y;
    
    if (this.delegate) {
      this.removeDelegate();
    }
    
    this.updateItem(e, dx, dy);
    this.item = null;
    this.origin = null;
  },
  
  updateItem(e, dx, dy) {
    const model = this.item.getModel();
    this.graph.updateItem(this.item, {
      x: model.x + dx,
      y: model.y + dy
    });
  }
});

// Selection behavior
registerBehavior('click-select', {
  getDefaultCfg() {
    return {
      multiple: true,
      trigger: 'shift'
    };
  },
  
  getEvents() {
    return {
      'node:click': 'onItemClick',
      'edge:click': 'onItemClick',
      'canvas:click': 'onCanvasClick'
    };
  },
  
  onItemClick(e) {
    const item = e.item;
    const selected = item.hasState('selected');
    
    if (this.multiple && e.originalEvent[this.trigger + 'Key']) {
      // Multi-select with modifier key
      this.graph.setItemState(item, 'selected', !selected);
    } else {
      // Single select - clear others first
      this.clearSelected();
      this.graph.setItemState(item, 'selected', true);
    }
  },
  
  onCanvasClick(e) {
    this.clearSelected();
  },
  
  clearSelected() {
    const selectedNodes = this.graph.findAllByState('node', 'selected');
    const selectedEdges = this.graph.findAllByState('edge', 'selected');
    
    [...selectedNodes, ...selectedEdges].forEach(item => {
      this.graph.setItemState(item, 'selected', false);
    });
  }
});

// Zoom canvas behavior
registerBehavior('zoom-canvas', {
  getDefaultCfg() {
    return {
      sensitivity: 2,
      minZoom: 0.1,
      maxZoom: 10
    };
  },
  
  getEvents() {
    return {
      wheel: 'onWheel'
    };
  },
  
  onWheel(e) {
    e.originalEvent.preventDefault();
    
    const graph = this.graph;
    const zoom = graph.getZoom();
    const ratio = zoom - (e.wheelDelta * this.sensitivity) / 100;
    
    if (ratio > this.maxZoom || ratio < this.minZoom) {
      return;
    }
    
    graph.zoomTo(ratio, { x: e.clientX, y: e.clientY });
  }
});

Behavior Management

Check and retrieve registered behaviors.

/**
 * Static behavior management class
 */
class Behavior {
  /**
   * Check if behavior type is registered
   * @param type - Behavior type name
   * @returns True if behavior exists
   */
  static hasBehavior(type: string): boolean;
  
  /**
   * Get registered behavior implementation
   * @param type - Behavior type name
   * @returns Behavior implementation object
   */
  static getBehavior(type: string): any;
}

Usage Examples:

import { Behavior } from "@antv/g6-core";

// Check if behavior exists before using
if (Behavior.hasBehavior('drag-node')) {
  // Use the behavior
  graph.addBehaviors(['drag-node'], 'default');
}

// Get behavior implementation for inspection
const dragBehavior = Behavior.getBehavior('drag-node');

Types

interface IBehavior {
  getEvents(): { [key in G6Event]?: string };
  getDefaultCfg?(): object;
  shouldBegin?(e?: IG6GraphEvent): boolean;
  shouldUpdate?(e?: IG6GraphEvent): boolean;
  shouldEnd?(e?: IG6GraphEvent): boolean;
  bind?(graph: IAbstractGraph): void;
  unbind?(graph: IAbstractGraph): void;
}

interface ModeOption {
  type: string;
  [key: string]: any;
}

type ModeType = string | ModeOption;

interface Modes {
  [modeName: string]: ModeType[];
}

type Item = INode | IEdge | ICombo;

interface IAbstractGraph {
  // Graph interface methods for behavior access
  setItemState(item: Item | string, state: string, value: string | boolean): void;
  addBehaviors(behaviors: string | ModeOption | ModeType[], modes: string | string[]): IAbstractGraph;
  removeBehaviors(behaviors: string | ModeOption | ModeType[], modes: string | string[]): IAbstractGraph;
  updateItem(item: Item | string, cfg: any, stack?: boolean): void;
  findAllByState<T extends Item>(type: string, state: string): T[];
  getZoom(): number;
  zoomTo(ratio: number, center?: { x: number; y: number }): void;
  // ... other graph methods
}