CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-d3-force

Force-directed graph layout using velocity Verlet integration for simulating physical forces on particles

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

links.mddocs/

Link Forces

The link force creates spring-like connections between nodes, pushing linked nodes together or apart according to desired link distance. It's essential for graph layouts and network visualizations, with configurable strength based on node connectivity.

Capabilities

Link Force Factory

Creates a new link force with specified links array.

/**
 * Creates a new link force with the specified links array
 * @param links - Array of link objects (optional, defaults to empty array)
 * @returns LinkForce instance with configuration methods
 */
function forceLink(links?: Link[]): LinkForce;

Usage Examples:

import { forceLink } from "d3-force";

// Create with links array
const links = [
  { source: 0, target: 1 },
  { source: 1, target: 2 }
];
const linkForce = forceLink(links);

// Create empty and add links later
const linkForce = forceLink();
linkForce.links(links);

// Add to simulation
simulation.force("link", forceLink(links));

Links Configuration

Configure the array of links for the force.

/**
 * Sets or gets the array of links associated with this force
 * @param links - Array of link objects (optional)
 * @returns Current links array or force instance for chaining
 */
links(links?: Link[]): Link[] | LinkForce;

Usage Examples:

const linkForce = forceLink();

// Set links with numeric indices
const links = [
  { source: 0, target: 1 },
  { source: 1, target: 2 },
  { source: 2, target: 0 }
];
linkForce.links(links);

// Set links with string IDs (requires id accessor)
const namedLinks = [
  { source: "Alice", target: "Bob" },
  { source: "Bob", target: "Carol" }
];
linkForce.id(d => d.id).links(namedLinks);

// Get current links
const currentLinks = linkForce.links();

Node ID Configuration

Configure how nodes are identified for link source/target resolution.

/**
 * Sets or gets the node id accessor function
 * @param id - ID accessor function (optional)
 * @returns Current id accessor or force instance for chaining
 */
id(id?: (d: Node, i: number, nodes: Node[]) => string | number): ((d: Node, i: number, nodes: Node[]) => string | number) | LinkForce;

Usage Examples:

const linkForce = forceLink();

// Use node index (default)
linkForce.id(d => d.index);

// Use custom id property
linkForce.id(d => d.id);

// Use name property
linkForce.id(d => d.name);

// Complex id generation
linkForce.id((d, i) => d.customId || i);

Distance Configuration

Configure the desired distance between linked nodes.

/**
 * Sets or gets the distance accessor for links
 * @param distance - Distance value or accessor function (optional, defaults to 30)
 * @returns Current distance accessor or force instance for chaining
 */
distance(distance?: number | ((d: Link, i: number, links: Link[]) => number)): ((d: Link, i: number, links: Link[]) => number) | LinkForce;

Usage Examples:

const linkForce = forceLink(links);

// Fixed distance for all links
linkForce.distance(50);

// Variable distance based on link properties
linkForce.distance(d => d.distance || 30);

// Distance based on link type
linkForce.distance(d => {
  switch (d.type) {
    case "strong": return 20;
    case "weak": return 80;
    default: return 50;
  }
});

Strength Configuration

Configure the strength of link constraints.

/**
 * Sets or gets the strength accessor for links
 * @param strength - Strength value or accessor function (optional)
 * @returns Current strength accessor or force instance for chaining
 */
strength(strength?: number | ((d: Link, i: number, links: Link[]) => number)): ((d: Link, i: number, links: Link[]) => number) | LinkForce;

Usage Examples:

const linkForce = forceLink(links);

// Fixed strength for all links (overrides default calculation)
linkForce.strength(0.5);

// Variable strength based on link properties
linkForce.strength(d => d.strength || 0.3);

// Default: automatic strength based on connectivity
// (strength is automatically 1 / min(degree of source, degree of target))

Iterations Configuration

Configure the number of constraint resolution iterations per simulation tick.

/**
 * Sets or gets the number of iterations per application
 * @param iterations - Number of iterations (optional, defaults to 1)
 * @returns Current iteration count or force instance for chaining
 */
iterations(iterations?: number): number | LinkForce;

Usage Examples:

const linkForce = forceLink(links);

// Single iteration (default)
linkForce.iterations(1);

// Multiple iterations for rigid constraints
linkForce.iterations(3);

// High iterations for lattice structures
linkForce.iterations(5);

Common Usage Patterns

Basic Network Graph

Create a simple force-directed network:

const nodes = [
  { id: "A" },
  { id: "B" },
  { id: "C" }
];

const links = [
  { source: "A", target: "B" },
  { source: "B", target: "C" }
];

const simulation = forceSimulation(nodes)
  .force("link", forceLink(links).id(d => d.id))
  .force("charge", forceManyBody())
  .force("center", forceCenter(400, 300));

Hierarchical Network

Create networks with different link types and distances:

const links = [
  { source: "root", target: "child1", type: "parent" },
  { source: "root", target: "child2", type: "parent" },
  { source: "child1", target: "grandchild1", type: "parent" },
  { source: "child1", target: "child2", type: "sibling" }
];

const simulation = forceSimulation(nodes)
  .force("link", forceLink(links)
    .id(d => d.id)
    .distance(d => d.type === "parent" ? 50 : 80)
    .strength(d => d.type === "parent" ? 0.8 : 0.2)
  );

Grid/Lattice Layout

Create rigid grid structures with high iterations:

// Create grid links
const gridLinks = [];
for (let i = 0; i < width; i++) {
  for (let j = 0; j < height; j++) {
    const nodeId = i * height + j;
    if (i < width - 1) gridLinks.push({ source: nodeId, target: nodeId + height });
    if (j < height - 1) gridLinks.push({ source: nodeId, target: nodeId + 1 });
  }
}

const simulation = forceSimulation(gridNodes)
  .force("link", forceLink(gridLinks)
    .distance(20)
    .strength(1)
    .iterations(6) // High iterations for rigid grid
  );

Dynamic Link Updates

Add or remove links dynamically:

const linkForce = forceLink(initialLinks).id(d => d.id);
simulation.force("link", linkForce);

function addLink(sourceId, targetId) {
  const links = linkForce.links();
  links.push({ source: sourceId, target: targetId });
  
  // Update force with new links array
  linkForce.links(links);
  
  // Reheat simulation
  simulation.alpha(0.3).restart();
}

function removeLink(sourceId, targetId) {
  const links = linkForce.links().filter(link => 
    !(link.source.id === sourceId && link.target.id === targetId)
  );
  
  linkForce.links(links);
  simulation.alpha(0.3).restart();
}

Weighted Networks

Use link weights to determine strength and distance:

const weightedLinks = [
  { source: "A", target: "B", weight: 5 },
  { source: "B", target: "C", weight: 2 },
  { source: "A", target: "C", weight: 1 }
];

const simulation = forceSimulation(nodes)
  .force("link", forceLink(weightedLinks)
    .id(d => d.id)
    .distance(d => 100 / d.weight) // Shorter distance for stronger connections
    .strength(d => d.weight / 10)  // Higher strength for stronger connections
  );

Link Object Properties

Links are automatically enhanced with additional properties:

const link = {
  source: "A",        // Original: string/number/object
  target: "B",        // Original: string/number/object
  index: 0,           // Added: zero-based index in links array
  // source and target are replaced with actual node object references
};

// After force initialization:
console.log(link.source); // Node object with id "A"
console.log(link.target); // Node object with id "B"

Performance Considerations

  • Connectivity-Based Strength: Default strength calculation reduces rigidity for highly connected nodes
  • Link Index Caching: Link properties (distance, strength) are cached when force is initialized
  • Bias Calculation: Internal bias values optimize force distribution between source and target nodes
  • Iteration Trade-off: More iterations provide more stable constraints but increase computational cost

Key Characteristics

  • Spring Physics: Links act like springs with configurable rest length and stiffness
  • Automatic Strength: Default strength is inversely related to node connectivity for stability
  • Flexible Identification: Supports numeric indices, string IDs, or custom identification schemes
  • Iterative Constraint: Multiple iterations per tick can resolve complex constraint networks

Default Values

  • distance: 30
  • strength: Automatic based on connectivity (1 / min(source degree, target degree))
  • iterations: 1
  • id: d => d.index

docs

centering.md

collision.md

index.md

links.md

many-body.md

positioning.md

simulation.md

tile.json