or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

binding-animation.mdcore-diagram.mddata-models.mdgeometry-collections.mdgraphobject-hierarchy.mdindex.mdinteractive-tools.mdlayout-system.mdtheme-management.mdvisual-elements.md
tile.json

visual-elements.mddocs/

Visual Elements

Visual elements in GoJS provide the graphical components for displaying shapes, text, images, and other visual content within diagrams. These classes extend GraphObject and provide specialized rendering capabilities.

Capabilities

Shape

Displays geometric shapes, paths, and figures with extensive styling options.

class Shape extends GraphObject {
  /**
   * Creates a new Shape.
   * @param figure - Named figure or geometry string
   * @param init - Optional initialization properties
   */
  constructor(figure?: string, init?: Partial<Shape>);
  
  // Geometry
  figure: string;
  geometry: Geometry;
  geometryString: string;
  
  // Fill Properties
  fill: Brush | string;
  spot1: Spot;
  spot2: Spot;
  
  // Stroke Properties
  stroke: Brush | string;
  strokeWidth: number;
  strokeCap: string;
  strokeJoin: string;
  strokeMiterLimit: number;
  strokeDashArray: number[];
  strokeDashOffset: number;
  
  // Arrow Properties (for links)
  toArrow: string;
  fromArrow: string;
  arrowScale: number;
  
  // Sizing
  width: number;
  height: number;
  
  // Path Properties (for link shapes)
  isPanelMain: boolean;
  segmentIndex: number;
  segmentFraction: number;
  segmentOffset: Point;
  segmentOrientation: Orientation;
  
  // Port Properties
  portId: string;
  fromLinkable: boolean;
  toLinkable: boolean;
  fromLinkableDuplicates: boolean;
  toLinkableDuplicates: boolean;
  fromLinkableSelfNode: boolean;
  toLinkableSelfNode: boolean;
  fromSpot: Spot;
  toSpot: Spot;
  fromEndSegmentLength: number;
  toEndSegmentLength: number;
}

Built-in Figures:

// Basic shapes
'Rectangle', 'RoundedRectangle', 'Square', 'Circle', 'Ellipse', 'Triangle', 'Diamond'

// Arrows and connectors  
'LineH', 'LineV', 'BarH', 'BarV', 'MinusLine', 'PlusLine', 'XLine'

// Complex shapes
'Actor', 'Card', 'Collate', 'CreateRequest', 'Database', 'DataStorage', 'Document'
'ExternalOrganization', 'InternalStorage', 'Junction', 'LinedDocument', 'LoopLimit'
'ManualInput', 'ManualOperation', 'MessageFromUser', 'MicroForm', 'MultiDocument'
'MultiProcess', 'OffPageConnector', 'Or', 'PaperTape', 'PrimitiveFromCall'
'PrimitiveToCall', 'Procedure', 'Process', 'Sort', 'Start', 'Terminator'
'TransmittalTape'

// Arrow heads
'Standard', 'Open', 'Kite', 'BackwardOpen', 'BackwardClosed', 'Triangle'
'ReverseTriangle', 'Diamond', 'Circle', 'Line', 'BackwardLine'

Usage Examples:

// Basic rectangle shape
const rect = new go.Shape('Rectangle', {
  width: 100,
  height: 60,
  fill: 'lightblue',
  stroke: 'blue',
  strokeWidth: 2
});

// Circle with gradient fill
const circle = new go.Shape('Circle', {
  width: 50,
  height: 50,
  fill: go.Brush.linear(go.Spot.Top, go.Spot.Bottom, 'white', 'blue'),
  stroke: 'darkblue',
  strokeWidth: 3
});

// Custom geometry using path string
const customShape = new go.Shape({
  geometryString: 'M0 0 L40 0 L40 20 L20 30 L0 20 Z',
  fill: 'yellow',
  stroke: 'orange',
  strokeWidth: 2
});

// Port shape for node connections
const portShape = new go.Shape('Circle', {
  width: 8,
  height: 8,
  fill: 'white',
  stroke: 'black',
  portId: 'port1',
  fromLinkable: true,
  toLinkable: true,
  fromSpot: go.Spot.Center,
  toSpot: go.Spot.Center
});

TextBlock

Displays and allows editing of text with comprehensive formatting and styling options.

class TextBlock extends GraphObject {
  /**
   * Creates a new TextBlock.
   * @param text - Initial text content
   * @param init - Optional initialization properties
   */
  constructor(text?: string, init?: Partial<TextBlock>);
  
  // Text Content
  text: string;
  textFormat: TextFormat;
  
  // Font Properties
  font: string;
  stroke: Brush | string;
  
  // Alignment and Layout
  textAlign: string;
  verticalAlignment: Spot;
  flip: Flip;
  interval: number;
  spacing: number;
  lineHeight: number;
  
  // Multi-line Properties
  isMultiline: boolean;
  wrap: Wrap;
  overflow: TextOverflow;
  ellipsis: string;
  maxLines: number;
  
  // Editing
  editable: boolean;
  textEditor: HTMLElement;
  textValidation: ((tb: TextBlock, oldstr: string, newstr: string) => boolean) | null;
  
  // Measuring
  naturalBounds: Rect;
  isStrikethrough: boolean;
  isUnderline: boolean;
  
  // Formatting (for rich text)
  choices: string[];
  errorFunction: ((tool: Tool, oldstr: string, newstr: string) => void) | null;
  
  // Path-based Text (for links)
  segmentIndex: number;
  segmentFraction: number;
  segmentOffset: Point;
  segmentOrientation: Orientation;
  
  // Methods
  getDocumentBounds(): Rect;
  getLocalBounds(): Rect;
  measureText(txt: string, maxWidth?: number): Size;
}

Text Formatting Enum:

enum TextFormat {
  None = 'None',
  RichText = 'RichText',
  PlainText = 'PlainText'
}

enum Wrap {
  None = 'None',
  Fit = 'Fit',
  DesiredSize = 'DesiredSize',
  BreakAll = 'BreakAll'
}

enum TextOverflow {
  Clip = 'Clip',
  Ellipsis = 'Ellipsis'
}

Usage Examples:

// Basic text block
const text = new go.TextBlock('Hello World', {
  font: '14pt sans-serif',
  stroke: 'black',
  textAlign: 'center'
});

// Editable text with validation
const editableText = new go.TextBlock({
  text: 'Click to edit',
  font: 'bold 12pt sans-serif',
  stroke: 'blue',
  editable: true,
  textValidation: (tb, oldstr, newstr) => {
    return newstr.length <= 20; // limit to 20 characters
  }
})
.bind('text', 'name');

// Multi-line text block
const multilineText = new go.TextBlock({
  text: 'This is a long text that will wrap across multiple lines',
  font: '10pt sans-serif',
  stroke: 'darkgreen',
  width: 100,
  isMultiline: true,
  wrap: go.Wrap.Fit,
  textAlign: 'left'
});

// Rich text formatting
const richText = new go.TextBlock({
  text: 'This is <b>bold</b> and this is <i>italic</i>',
  textFormat: go.TextFormat.RichText,
  font: '12pt sans-serif'
});

// Text along link path
const linkText = new go.TextBlock('Link Label', {
  segmentIndex: 0,
  segmentOffset: new go.Point(NaN, NaN), // center on segment
  segmentOrientation: go.Orientation.Upright,
  font: '10pt sans-serif',
  stroke: 'white',
  background: 'black'
});

Picture

Displays images and media content with scaling and alignment options.

class Picture extends GraphObject {
  /**
   * Creates a new Picture.
   * @param source - Image source URL or data URI
   * @param init - Optional initialization properties
   */
  constructor(source?: string, init?: Partial<Picture>);
  
  // Static methods
  static clearCache(url?: string): void;
  
  // Image Source Properties
  source: string;
  element: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | null;
  sourceCrossOrigin: ((a: Picture) => string) | null;
  
  // Display Properties
  imageStretch: ImageStretch;
  imageAlignment: Spot;
  flip: Flip;
  sourceRect: Rect;
  
  // Event Handlers
  successFunction: ((pic: Picture, e: Event) => void) | null;
  errorFunction: ((pic: Picture, e: Event) => void) | null;
  
  // Read-only Properties
  naturalBounds: Rect;
  
  // Methods
  reloadSource(): void;
  redraw(): void;
}

Image Stretch Enum:

enum ImageStretch {
  None = 0,           // No scaling, may clip
  Fill = 2,           // Scale to fit exactly, may stretch aspect ratio  
  Uniform = 6,        // Scale equally to fit larger side
  UniformToFill = 7   // Scale equally to fill bounds, may clip
}

Usage Examples:

// Basic image
const picture = new go.Picture('https://example.com/image.png', {
  width: 100,
  height: 100,
  imageStretch: go.ImageStretch.Uniform
});

// Image with loading handlers
const imageWithHandlers = new go.Picture({
  source: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  width: 50,
  height: 50,
  successFunction: (pic, e) => {
    console.log('Image loaded successfully');
  },
  errorFunction: (pic, e) => {
    console.log('Failed to load image');
    pic.source = 'default-image.png'; // fallback
  }
});

// Scaled image that maintains aspect ratio
const scaledImage = new go.Picture('icon.svg', {
  width: 32,
  height: 32,
  imageStretch: go.ImageStretch.Uniform,
  imageAlignment: go.Spot.Center
});

Placeholder

Placeholder elements used in templates to indicate where content should be positioned.

class Placeholder extends GraphObject {
  /**
   * Creates a new Placeholder.
   * @param init - Optional initialization properties
   */
  constructor(init?: Partial<Placeholder>);
  
  // Padding around placeholder content
  padding: Margin;
}

Usage Examples:

// Group template with placeholder for members
const groupTemplate = new go.Group('Auto')
.add(
  new go.Shape('RoundedRectangle', {
    fill: 'rgba(128,128,128,0.33)',
    stroke: 'black'
  }),
  new go.Panel('Vertical', { defaultAlignment: go.Spot.Left })
    .add(
      new go.TextBlock({
        font: 'bold 12pt sans-serif',
        margin: 4
      })
        .bind('text', 'text'),
      new go.Placeholder({
        padding: 5,
        alignment: go.Spot.TopLeft
      })
    )
);

// Adornment with placeholder
const adornmentTemplate = new go.Adornment('Auto')
.add(
  new go.Shape({
    fill: null,
    stroke: 'dodgerblue',
    strokeWidth: 3
  }),
  new go.Placeholder()
);

Common Patterns

Creating Custom Figures

// Register custom figure
go.Shape.defineFigureGenerator('CustomStar', (shape, w, h) => {
  const geo = new go.Geometry();
  const fig = new go.PathFigure(w * 0.5, 0, true);
  geo.add(fig);
  
  // Create star points
  for (let i = 0; i < 10; i++) {
    const angle = i * Math.PI / 5;
    const radius = (i % 2 === 0) ? w * 0.5 : w * 0.2;
    const x = w * 0.5 + radius * Math.cos(angle - Math.PI / 2);
    const y = h * 0.5 + radius * Math.sin(angle - Math.PI / 2);
    fig.add(new go.PathSegment(go.SegmentType.Line, x, y));
  }
  fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.5, 0).close());
  
  return geo;
});

// Use custom figure
const customStar = new go.Shape('CustomStar', {
  width: 50,
  height: 50,
  fill: 'gold',
  stroke: 'orange'
});

Responsive Text Sizing

// Text that scales with shape
const responsiveNode = new go.Node('Auto')
.add(
  new go.Shape('RoundedRectangle', { fill: 'white', stroke: 'black' })
    .bind('desiredSize', 'size', go.Size.parse),
  new go.TextBlock({
    margin: 8,
    textAlign: 'center',
    verticalAlignment: go.Spot.Center,
    wrap: go.Wrap.Fit,
    font: '12pt sans-serif'
  })
    .bind('text')
    .bind('font', 'size', (sz) => {
      const size = go.Size.parse(sz);
      const fontSize = Math.max(8, Math.min(16, size.width / 8));
      return `${fontSize}pt sans-serif`;
    })
);

Image Fallback Pattern

// Image with automatic fallback
const imageWithFallback = new go.Picture({
  width: 40,
  height: 40,
  imageStretch: go.ImageStretch.Uniform,
  errorFunction: (pic) => {
    // Replace with default icon on error
    pic.source = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMCA5TDEzLjA5IDE1Ljc0TDEyIDIyTDEwLjkxIDE1Ljc0TDQgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNzc3Ii8+Cjwvc3ZnPgo=';
  }
})
.bind('source', 'image');