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

positioning.mddocs/

Positioning Forces

Positioning forces push nodes toward desired positions along specific dimensions or toward circular positions. They include x-positioning, y-positioning, and radial positioning forces that are ideal for creating organized layouts and constraining nodes to specific areas.

Capabilities

X-Positioning Force

Creates a positioning force along the x-axis toward a specified position.

/**
 * Creates a new positioning force along the x-axis
 * @param x - Target x position (number or accessor function, optional, defaults to 0)
 * @returns XForce instance with configuration methods
 */
function forceX(x?: number | ((d: Node, i: number, nodes: Node[]) => number)): XForce;

Usage Examples:

import { forceX } from "d3-force";

// Push all nodes toward x = 400
const xForce = forceX(400);

// Variable x position based on node data
const xForce = forceX(d => d.targetX || 200);

// Push toward center of viewport
const xForce = forceX(width / 2);

Y-Positioning Force

Creates a positioning force along the y-axis toward a specified position.

/**
 * Creates a new positioning force along the y-axis
 * @param y - Target y position (number or accessor function, optional, defaults to 0)
 * @returns YForce instance with configuration methods
 */
function forceY(y?: number | ((d: Node, i: number, nodes: Node[]) => number)): YForce;

Usage Examples:

import { forceY } from "d3-force";

// Push all nodes toward y = 300
const yForce = forceY(300);

// Variable y position based on node data
const yForce = forceY(d => d.level * 50);

// Push toward center of viewport
const yForce = forceY(height / 2);

Radial Positioning Force

Creates a positioning force toward a circle of specified radius.

/**
 * Creates a new radial positioning force toward a circle
 * @param radius - Target radius (number or accessor function, required)
 * @param x - Circle center x coordinate (optional, defaults to 0)
 * @param y - Circle center y coordinate (optional, defaults to 0)
 * @returns RadialForce instance with configuration methods
 */
function forceRadial(radius: number | ((d: Node, i: number, nodes: Node[]) => number), x?: number, y?: number): RadialForce;

Usage Examples:

import { forceRadial } from "d3-force";

// Push nodes toward circle of radius 100 at origin
const radialForce = forceRadial(100);

// Circle centered at specific coordinates
const radialForce = forceRadial(150, 400, 300);

// Variable radius based on node data
const radialForce = forceRadial(d => d.layer * 50, 400, 300);

X-Force Configuration

X Position Configuration

/**
 * Sets or gets the target x position accessor
 * @param x - Target x position (number or accessor function, optional)
 * @returns Current x accessor or force instance for chaining
 */
x(x?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | XForce;

X Strength Configuration

/**
 * Sets or gets the x-positioning strength accessor
 * @param strength - Strength value or accessor function (optional, defaults to 0.1)
 * @returns Current strength accessor or force instance for chaining
 */
strength(strength?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | XForce;

Y-Force Configuration

Y Position Configuration

/**
 * Sets or gets the target y position accessor
 * @param y - Target y position (number or accessor function, optional)
 * @returns Current y accessor or force instance for chaining
 */
y(y?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | YForce;

Y Strength Configuration

/**
 * Sets or gets the y-positioning strength accessor
 * @param strength - Strength value or accessor function (optional, defaults to 0.1)
 * @returns Current strength accessor or force instance for chaining
 */
strength(strength?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | YForce;

Radial Force Configuration

Radial Strength Configuration

/**
 * Sets or gets the radial positioning strength accessor
 * @param strength - Strength value or accessor function (optional, defaults to 0.1)
 * @returns Current strength accessor or force instance for chaining
 */
strength(strength?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | RadialForce;

Radial Radius Configuration

/**
 * Sets or gets the target radius accessor
 * @param radius - Target radius (number or accessor function, optional)
 * @returns Current radius accessor or force instance for chaining
 */
radius(radius?: number | ((d: Node, i: number, nodes: Node[]) => number)): ((d: Node, i: number, nodes: Node[]) => number) | RadialForce;

Radial Center Configuration

/**
 * Sets or gets the x-coordinate of the circle center
 * @param x - Center x coordinate (optional)
 * @returns Current x coordinate or force instance for chaining
 */
x(x?: number): number | RadialForce;

/**
 * Sets or gets the y-coordinate of the circle center
 * @param y - Center y coordinate (optional)
 * @returns Current y coordinate or force instance for chaining
 */
y(y?: number): number | RadialForce;

Common Usage Patterns

Beeswarm Plots

Create one-dimensional scatter plots with collision:

// Horizontal beeswarm
const simulation = forceSimulation(data)
  .force("x", forceX(d => xScale(d.value)).strength(0.8))
  .force("y", forceY(height / 2).strength(0.1))
  .force("collide", forceCollide(3));

// Vertical beeswarm  
const simulation = forceSimulation(data)
  .force("x", forceX(width / 2).strength(0.1))
  .force("y", forceY(d => yScale(d.value)).strength(0.8))
  .force("collide", forceCollide(3));

Hierarchical Layouts

Position nodes by level or category:

const simulation = forceSimulation(nodes)
  .force("x", forceX(d => {
    switch(d.category) {
      case "A": return 200;
      case "B": return 400;
      case "C": return 600;
      default: return 400;
    }
  }).strength(0.5))
  .force("y", forceY(d => d.level * 100).strength(0.8))
  .force("charge", forceManyBody().strength(-50));

Circular Layouts

Create layered circular arrangements:

const simulation = forceSimulation(nodes)
  .force("radial", forceRadial(d => d.layer * 80, 400, 300).strength(0.7))
  .force("charge", forceManyBody().strength(-30))
  .force("collide", forceCollide(5));

Constrained Network Layout

Keep network within specific bounds:

const simulation = forceSimulation(nodes)
  .force("link", forceLink(links))
  .force("charge", forceManyBody())
  .force("center", forceCenter(400, 300))
  .force("x", forceX(400).strength(0.1)) // Weak pull toward center
  .force("y", forceY(300).strength(0.1)); // Weak pull toward center

Matrix/Grid Positioning

Position nodes in grid-like arrangements:

const gridSize = Math.ceil(Math.sqrt(nodes.length));

const simulation = forceSimulation(nodes)
  .force("x", forceX((d, i) => (i % gridSize) * 50).strength(0.8))
  .force("y", forceY((d, i) => Math.floor(i / gridSize) * 50).strength(0.8))
  .force("collide", forceCollide(20));

Dynamic Positioning

Update target positions based on user interaction:

const xForce = forceX(d => d.targetX || 400);
const yForce = forceY(d => d.targetY || 300);

simulation
  .force("x", xForce)
  .force("y", yForce);

function moveNodesTo(nodes, newPositions) {
  nodes.forEach((node, i) => {
    node.targetX = newPositions[i].x;
    node.targetY = newPositions[i].y;
  });
  
  // Update force accessors
  xForce.x(d => d.targetX);
  yForce.y(d => d.targetY);
  
  // Reheat simulation
  simulation.alpha(0.3).restart();
}

Responsive Circular Layouts

Adjust radial positioning based on container size:

const radialForce = forceRadial(100, width / 2, height / 2);
simulation.force("radial", radialForce);

window.addEventListener("resize", () => {
  const newWidth = window.innerWidth;
  const newHeight = window.innerHeight;
  const newRadius = Math.min(newWidth, newHeight) * 0.3;
  
  radialForce
    .radius(newRadius)
    .x(newWidth / 2)
    .y(newHeight / 2);
    
  simulation.alpha(0.3).restart();
});

Multi-Ring Radial Layout

Create concentric circles with different radii:

const simulation = forceSimulation(nodes)
  .force("radial", forceRadial(d => {
    switch(d.ring) {
      case 0: return 50;  // Inner ring
      case 1: return 120; // Middle ring
      case 2: return 200; // Outer ring
      default: return 100;
    }
  }, 400, 300).strength(0.8))
  .force("charge", forceManyBody().strength(-20))
  .force("collide", forceCollide(8));

Strength Guidelines

Positioning force strength determines how quickly nodes move toward target positions:

  • 0.1 (default): Gentle positioning, good for maintaining other force effects
  • 0.3-0.5: Moderate positioning, balances with other forces
  • 0.8-1.0: Strong positioning, dominates other forces
  • > 1.0: Not recommended, can cause instability

Force Calculation

Positioning forces apply velocity changes proportional to distance from target:

// For X positioning
node.vx += (targetX - node.x) * strength * alpha;

// For Y positioning  
node.vy += (targetY - node.y) * strength * alpha;

// For radial positioning
const dx = node.x - centerX;
const dy = node.y - centerY;
const distance = Math.sqrt(dx * dx + dy * dy);
const force = (targetRadius - distance) * strength * alpha / distance;
node.vx += dx * force;
node.vy += dy * force;

Key Characteristics

  • Proportional Force: Force strength is proportional to distance from target
  • Gradual Movement: Nodes move gradually toward targets rather than jumping
  • Alpha Scaling: Force strength scales with simulation alpha (temperature)
  • Non-Destructive: Works well in combination with other forces
  • Flexible Targeting: Supports both fixed positions and dynamic target functions

Default Values

  • x: 0 (for forceX)
  • y: 0 (for forceY)
  • radius: No default (required parameter for forceRadial)
  • strength: 0.1 for all positioning forces
  • center: ⟨0,0⟩ for forceRadial

docs

centering.md

collision.md

index.md

links.md

many-body.md

positioning.md

simulation.md

tile.json