Files
jarvis-at-skic 3347cc342c feat: draw.io custom shapes analysis + buildable example plugin
- ANALYSIS.md: Full architecture analysis of draw.io shape systems
  (XML stencils vs JS shapes, plugin loading, desktop/web support)
- Example plugin with 5 custom shapes demonstrating JS logic:
  - StatusIndicator: conditional rendering based on status param
  - ProgressBar: computed geometry (percentage-based fill)
  - DataFlowArrow: dynamic arrows with direction/speed params
  - HexagonCluster: loop-based hexagonal grid generation
  - MetricGauge: radial gauge with arc computation + zones
- Webpack build pipeline (npm run build / build:dev / watch)
- Pre-built dist/drawio-custom-shapes.js ready for installation
- Full README with installation instructions for desktop + web
2026-07-24 15:57:59 +00:00

4.5 KiB

draw.io Custom Shapes Example Plugin

A fully buildable example plugin demonstrating how to create custom draw.io shapes with JavaScript logic.

What This Is

A draw.io plugin that registers custom shapes with programmatic rendering — shapes that use conditionals, loops, computed geometry, and style-reactive behavior. Unlike XML stencils (which are purely declarative), these shapes have full JavaScript power.

Quick Start

# Install dependencies
npm install

# Development build (with source maps)
npm run build:dev

# Production build (minified)
npm run build

# Watch mode (rebuild on changes)
npm run watch

Output: dist/drawio-custom-shapes.js

Installation in draw.io

Desktop App (Electron)

  1. Build the plugin: npm run build
  2. Open draw.io desktop
  3. Extras > Plugins
  4. Enable external plugins if prompted
  5. Click "Select File..." → navigate to dist/drawio-custom-shapes.js
  6. Restart draw.io
  7. Find "Custom Shapes Example" palette in the sidebar

Self-Hosted (Docker)

  1. Build the plugin: npm run build
  2. Copy dist/drawio-custom-shapes.js to your draw.io plugins directory
  3. Set environment: DRAWIO_PLUGINS_ALLOW_CUSTOM=true
  4. Add to configuration:
    {
      "plugins": ["/plugins/drawio-custom-shapes.js"]
    }
    
  5. Restart the container

Web (URL parameter)

If you host the plugin file at a URL:

https://your-drawio.com/?p=YOUR_PLUGIN_KEY

Project Structure

├── src/
│   ├── index.js              # Plugin entry point (Draw.loadPlugin wrapper)
│   ├── shapes/
│   │   ├── StatusIndicator.js    # Conditional rendering based on status
│   │   ├── ProgressBar.js        # Computed geometry (percentage-based)
│   │   ├── DataFlowArrow.js      # Dynamic arrow with animation markers
│   │   ├── HexagonCluster.js     # Loop-based hexagonal grid
│   │   └── MetricGauge.js        # Radial gauge with computed arcs
│   └── palette.js            # Sidebar palette registration
├── dist/                     # Build output
├── webpack.config.js         # Build configuration
├── package.json
├── ANALYSIS.md               # Full architecture analysis
└── README.md

Shape Catalog

1. Status Indicator (customShapes.statusIndicator)

A shape that changes color and icon based on a status style parameter.

  • Styles: status=ok|warning|error|unknown
  • Demonstrates: conditional rendering, style reading

2. Progress Bar (customShapes.progressBar)

A horizontal bar that fills based on a percentage value.

  • Styles: progress=0..100, barColor=#4CAF50
  • Demonstrates: computed geometry, value-based rendering

3. Data Flow Arrow (customShapes.dataFlowArrow)

A directional arrow with animated flow indicators.

  • Styles: direction=right|left|both, flowSpeed=fast|medium|slow
  • Demonstrates: dynamic path generation, pattern rendering

4. Hexagon Cluster (customShapes.hexCluster)

A grid of hexagons that adapts to the cell size.

  • Styles: hexCount=7, hexFill=#E3F2FD
  • Demonstrates: loop-based drawing, mathematical geometry

5. Metric Gauge (customShapes.metricGauge)

A radial gauge (speedometer-style) showing a value within a range.

  • Styles: value=75, minVal=0, maxVal=100, zones=green,yellow,red
  • Demonstrates: arc computation, gradient zones, text rendering

Customizing

Adding a New Shape

  1. Create a new file in src/shapes/YourShape.js:
import { registerShape, getValue } from '../utils';

export function YourShapeName() {
    mxShape.call(this);
}

mxUtils.extend(YourShapeName, mxShape);

YourShapeName.prototype.paintVertexShape = function(c, x, y, w, h) {
    c.translate(x, y);

    // Read style parameters
    var myParam = getValue(this.style, 'myParam', 'default');

    // Draw with full JS logic
    c.begin();
    c.moveTo(0, 0);
    c.lineTo(w, h);
    c.stroke();
};

// Register the shape
registerShape('customShapes.yourShape', YourShapeName);
  1. Import it in src/index.js
  2. Add a palette entry in src/palette.js
  3. Rebuild: npm run build

Style Parameters

Shapes read parameters from the cell's style string:

shape=customShapes.yourShape;myParam=value;fillColor=#fff;

Access in code:

var val = mxUtils.getValue(this.style, 'myParam', 'default');

Architecture Notes

See ANALYSIS.md for the full technical analysis of how draw.io's shape systems work, including the stencil registry, cell renderer, and plugin loading mechanisms.

License

MIT