mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-15 05:19:58 +02:00
#1295 Added the flowchart shapes
This commit is contained in:
@@ -107,14 +107,15 @@
|
|||||||
a <--> b
|
a <--> b
|
||||||
b o--o c
|
b o--o c
|
||||||
c x--x d
|
c x--x d
|
||||||
a2 --> b2
|
a21([In the box]) --> b2
|
||||||
b2 --o c2
|
b2((b2)) --o c2
|
||||||
c2 --x d2
|
c2(c2) --x d2 --> id1{{This is the text in the box}} --> A[(cylindrical<br />shape<br />test)]
|
||||||
</div>
|
</div>
|
||||||
old:
|
old:
|
||||||
<div class="mermaid" style="width: 100%; height: 100%">
|
<div class="mermaid" style="width: 100%; height: 100%">
|
||||||
graph LR
|
graph LR
|
||||||
a --> b
|
a((a)) --> b --> id1{{This is the text in the box}}
|
||||||
|
A[(cylindrical<br />shape<br />test)]
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
* Borrowed with love from from dagrge-d3. Many thanks to cpettitt!
|
* Borrowed with love from from dagrge-d3. Many thanks to cpettitt!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import node from './intersect-node';
|
import node from './intersect-node.js';
|
||||||
import circle from './intersect-circle';
|
import circle from './intersect-circle.js';
|
||||||
import ellipse from './intersect-ellipse';
|
import ellipse from './intersect-ellipse.js';
|
||||||
import polygon from './intersect-polygon';
|
import polygon from './intersect-polygon.js';
|
||||||
import rect from './intersect-rect';
|
import rect from './intersect-rect.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
node,
|
node,
|
||||||
|
@@ -1,17 +1,14 @@
|
|||||||
import intersectRect from './intersect/intersect-rect';
|
import intersect from './intersect/index.js';
|
||||||
import { logger } from '../logger'; // eslint-disable-line
|
import { logger } from '../logger'; // eslint-disable-line
|
||||||
import createLabel from './createLabel';
|
import createLabel from './createLabel';
|
||||||
|
|
||||||
const rect = (parent, node) => {
|
const labelHelper = (parent, node) => {
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
.insert('g')
|
.insert('g')
|
||||||
.attr('class', 'node default')
|
.attr('class', 'node default')
|
||||||
.attr('id', node.id);
|
.attr('id', node.id);
|
||||||
|
|
||||||
// add the rect
|
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
|
||||||
|
|
||||||
// Create the label and insert it after the rect
|
// Create the label and insert it after the rect
|
||||||
const label = shapeSvg.insert('g').attr('class', 'label');
|
const label = shapeSvg.insert('g').attr('class', 'label');
|
||||||
|
|
||||||
@@ -22,7 +19,279 @@ const rect = (parent, node) => {
|
|||||||
|
|
||||||
const halfPadding = node.padding / 2;
|
const halfPadding = node.padding / 2;
|
||||||
|
|
||||||
// center the rect around its coordinate
|
// Center the label
|
||||||
|
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
|
||||||
|
|
||||||
|
return { shapeSvg, bbox, halfPadding, label };
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateNodeBounds = (node, element) => {
|
||||||
|
const bbox = element.node().getBBox();
|
||||||
|
node.width = bbox.width;
|
||||||
|
node.height = bbox.height;
|
||||||
|
};
|
||||||
|
|
||||||
|
function insertPolygonShape(parent, w, h, points) {
|
||||||
|
return parent
|
||||||
|
.insert('polygon', ':first-child')
|
||||||
|
.attr(
|
||||||
|
'points',
|
||||||
|
points
|
||||||
|
.map(function(d) {
|
||||||
|
return d.x + ',' + d.y;
|
||||||
|
})
|
||||||
|
.join(' ')
|
||||||
|
)
|
||||||
|
.attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')');
|
||||||
|
}
|
||||||
|
const question = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const s = (w + h) * 0.9;
|
||||||
|
const points = [
|
||||||
|
{ x: s / 2, y: 0 },
|
||||||
|
{ x: s, y: -s / 2 },
|
||||||
|
{ x: s / 2, y: -s },
|
||||||
|
{ x: 0, y: -s / 2 }
|
||||||
|
];
|
||||||
|
|
||||||
|
const questionElem = insertPolygonShape(shapeSvg, s, s, points);
|
||||||
|
updateNodeBounds(node, questionElem);
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polugon(node, points, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hexagon = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const f = 4;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const m = h / f;
|
||||||
|
const w = bbox.width + 2 * m + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: m, y: 0 },
|
||||||
|
{ x: w - m, y: 0 },
|
||||||
|
{ x: w, y: -h / 2 },
|
||||||
|
{ x: w - m, y: -h },
|
||||||
|
{ x: m, y: -h },
|
||||||
|
{ x: 0, y: -h / 2 }
|
||||||
|
];
|
||||||
|
const hex = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, hex);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rect_left_inv_arrow = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: -h / 2, y: 0 },
|
||||||
|
{ x: w, y: 0 },
|
||||||
|
{ x: w, y: -h },
|
||||||
|
{ x: -h / 2, y: -h },
|
||||||
|
{ x: 0, y: -h / 2 }
|
||||||
|
];
|
||||||
|
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
const lean_right = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: (-2 * h) / 6, y: 0 },
|
||||||
|
{ x: w - h / 6, y: 0 },
|
||||||
|
{ x: w + (2 * h) / 6, y: -h },
|
||||||
|
{ x: h / 6, y: -h }
|
||||||
|
];
|
||||||
|
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lean_left = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: (2 * h) / 6, y: 0 },
|
||||||
|
{ x: w + h / 6, y: 0 },
|
||||||
|
{ x: w - (2 * h) / 6, y: -h },
|
||||||
|
{ x: -h / 6, y: -h }
|
||||||
|
];
|
||||||
|
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const trapezoid = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: (-2 * h) / 6, y: 0 },
|
||||||
|
{ x: w + (2 * h) / 6, y: 0 },
|
||||||
|
{ x: w - h / 6, y: -h },
|
||||||
|
{ x: h / 6, y: -h }
|
||||||
|
];
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const inv_trapezoid = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: h / 6, y: 0 },
|
||||||
|
{ x: w - h / 6, y: 0 },
|
||||||
|
{ x: w + (2 * h) / 6, y: -h },
|
||||||
|
{ x: (-2 * h) / 6, y: -h }
|
||||||
|
];
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
const rect_right_inv_arrow = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const points = [
|
||||||
|
{ x: 0, y: 0 },
|
||||||
|
{ x: w + h / 2, y: 0 },
|
||||||
|
{ x: w, y: -h / 2 },
|
||||||
|
{ x: w + h / 2, y: -h },
|
||||||
|
{ x: 0, y: -h }
|
||||||
|
];
|
||||||
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.polygon(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
const cylinder = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const w = bbox.width + node.padding;
|
||||||
|
const rx = w / 2;
|
||||||
|
const ry = rx / (2.5 + w / 50);
|
||||||
|
const h = bbox.height + ry + node.padding;
|
||||||
|
|
||||||
|
const shape =
|
||||||
|
'M 0,' +
|
||||||
|
ry +
|
||||||
|
' a ' +
|
||||||
|
rx +
|
||||||
|
',' +
|
||||||
|
ry +
|
||||||
|
' 0,0,0 ' +
|
||||||
|
w +
|
||||||
|
' 0 a ' +
|
||||||
|
rx +
|
||||||
|
',' +
|
||||||
|
ry +
|
||||||
|
' 0,0,0 ' +
|
||||||
|
-w +
|
||||||
|
' 0 l 0,' +
|
||||||
|
h +
|
||||||
|
' a ' +
|
||||||
|
rx +
|
||||||
|
',' +
|
||||||
|
ry +
|
||||||
|
' 0,0,0 ' +
|
||||||
|
w +
|
||||||
|
' 0 l 0,' +
|
||||||
|
-h;
|
||||||
|
|
||||||
|
const el = shapeSvg
|
||||||
|
.attr('label-offset-y', ry)
|
||||||
|
.insert('path', ':first-child')
|
||||||
|
.attr('d', shape)
|
||||||
|
.attr('transform', 'translate(' + -w / 2 + ',' + -(h / 2 + ry) + ')');
|
||||||
|
|
||||||
|
updateNodeBounds(node, el);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
const pos = intersect.rect(node, point);
|
||||||
|
const x = pos.x - node.x;
|
||||||
|
|
||||||
|
if (
|
||||||
|
rx != 0 &&
|
||||||
|
(Math.abs(x) < node.width / 2 ||
|
||||||
|
(Math.abs(x) == node.width / 2 && Math.abs(pos.y - node.y) > node.height / 2 - ry))
|
||||||
|
) {
|
||||||
|
// ellipsis equation: x*x / a*a + y*y / b*b = 1
|
||||||
|
// solve for y to get adjustion value for pos.y
|
||||||
|
let y = ry * ry * (1 - (x * x) / (rx * rx));
|
||||||
|
if (y != 0) y = Math.sqrt(y);
|
||||||
|
y = ry - y;
|
||||||
|
if (point.y - node.y > 0) y = -y;
|
||||||
|
|
||||||
|
pos.y += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rect = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
// add the rect
|
||||||
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
rect
|
rect
|
||||||
.attr('rx', node.rx)
|
.attr('rx', node.rx)
|
||||||
.attr('ry', node.ry)
|
.attr('ry', node.ry)
|
||||||
@@ -31,21 +300,74 @@ const rect = (parent, node) => {
|
|||||||
.attr('width', bbox.width + node.padding)
|
.attr('width', bbox.width + node.padding)
|
||||||
.attr('height', bbox.height + node.padding);
|
.attr('height', bbox.height + node.padding);
|
||||||
|
|
||||||
// Center the label
|
updateNodeBounds(node, rect);
|
||||||
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
|
|
||||||
|
|
||||||
const rectBox = rect.node().getBBox();
|
|
||||||
node.width = rectBox.width;
|
|
||||||
node.height = rectBox.height;
|
|
||||||
|
|
||||||
node.intersect = function(point) {
|
node.intersect = function(point) {
|
||||||
return intersectRect(node, point);
|
return intersect.rect(node, point);
|
||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
};
|
||||||
|
|
||||||
const shapes = { rect };
|
const stadium = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
|
|
||||||
|
const h = bbox.height + node.padding;
|
||||||
|
const w = bbox.width + h / 4 + node.padding;
|
||||||
|
|
||||||
|
// add the rect
|
||||||
|
const rect = shapeSvg
|
||||||
|
.insert('rect', ':first-child')
|
||||||
|
.attr('rx', h / 2)
|
||||||
|
.attr('ry', h / 2)
|
||||||
|
.attr('x', -w / 2)
|
||||||
|
.attr('y', -h / 2)
|
||||||
|
.attr('width', w)
|
||||||
|
.attr('height', h);
|
||||||
|
|
||||||
|
updateNodeBounds(node, rect);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.rect(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
const circle = (parent, node) => {
|
||||||
|
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node);
|
||||||
|
const circle = shapeSvg.insert('circle', ':first-child');
|
||||||
|
|
||||||
|
// center the circle around its coordinate
|
||||||
|
circle
|
||||||
|
.attr('rx', node.rx)
|
||||||
|
.attr('ry', node.ry)
|
||||||
|
.attr('r', bbox.width / 2 + halfPadding)
|
||||||
|
.attr('width', bbox.width + node.padding)
|
||||||
|
.attr('height', bbox.height + node.padding);
|
||||||
|
|
||||||
|
updateNodeBounds(node, circle);
|
||||||
|
|
||||||
|
node.intersect = function(point) {
|
||||||
|
return intersect.circle(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const shapes = {
|
||||||
|
question,
|
||||||
|
rect,
|
||||||
|
circle,
|
||||||
|
stadium,
|
||||||
|
hexagon,
|
||||||
|
rect_left_inv_arrow,
|
||||||
|
lean_right,
|
||||||
|
lean_left,
|
||||||
|
trapezoid,
|
||||||
|
inv_trapezoid,
|
||||||
|
rect_right_inv_arrow,
|
||||||
|
cylinder
|
||||||
|
};
|
||||||
|
|
||||||
let nodeElems = {};
|
let nodeElems = {};
|
||||||
|
|
||||||
|
@@ -329,44 +329,6 @@ export const draw = function(text, id) {
|
|||||||
// Add custom shapes
|
// Add custom shapes
|
||||||
// flowChartShapes.addToRenderV2(addShape);
|
// flowChartShapes.addToRenderV2(addShape);
|
||||||
|
|
||||||
// Add our custom arrow - an empty arrowhead
|
|
||||||
// render.arrows().none = function normal(parent, id, edge, type) {
|
|
||||||
// const marker = parent
|
|
||||||
// .append('marker')
|
|
||||||
// .attr('id', id)
|
|
||||||
// .attr('viewBox', '0 0 10 10')
|
|
||||||
// .attr('refX', 9)
|
|
||||||
// .attr('refY', 5)
|
|
||||||
// .attr('markerUnits', 'strokeWidth')
|
|
||||||
// .attr('markerWidth', 8)
|
|
||||||
// .attr('markerHeight', 6)
|
|
||||||
// .attr('orient', 'auto');
|
|
||||||
|
|
||||||
// // const path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z');
|
|
||||||
// dagreD3.util.applyStyle(path, edge[type + 'Style']);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Override normal arrowhead defined in d3. Remove style & add class to allow css styling.
|
|
||||||
// render.arrows().normal = function normal(parent, id) {
|
|
||||||
// const marker = parent
|
|
||||||
// .append('marker')
|
|
||||||
// .attr('id', id)
|
|
||||||
// .attr('viewBox', '0 0 10 10')
|
|
||||||
// .attr('refX', 9)
|
|
||||||
// .attr('refY', 5)
|
|
||||||
// .attr('markerUnits', 'strokeWidth')
|
|
||||||
// .attr('markerWidth', 8)
|
|
||||||
// .attr('markerHeight', 6)
|
|
||||||
// .attr('orient', 'auto');
|
|
||||||
|
|
||||||
// marker
|
|
||||||
// .append('path')
|
|
||||||
// .attr('d', 'M 0 0 L 10 5 L 0 10 z')
|
|
||||||
// .attr('class', 'arrowheadPath')
|
|
||||||
// .style('stroke-width', 1)
|
|
||||||
// .style('stroke-dasharray', '1,0');
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Set up an SVG group so that we can translate the final graph.
|
// Set up an SVG group so that we can translate the final graph.
|
||||||
const svg = d3.select(`[id="${id}"]`);
|
const svg = d3.select(`[id="${id}"]`);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user