- 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
160 lines
4.5 KiB
Markdown
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
|