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

160 lines
4.5 KiB
Markdown

# 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
```bash
# 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:
```json
{
"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`:
```javascript
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);
```
2. Import it in `src/index.js`
3. Add a palette entry in `src/palette.js`
4. 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:
```javascript
var val = mxUtils.getValue(this.style, 'myParam', 'default');
```
## Architecture Notes
See [ANALYSIS.md](./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