#1295 Added the flowchart shapes

This commit is contained in:
Knut Sveidqvist
2020-03-18 22:08:19 +01:00
parent 4010c89899
commit 17f06564a2
4 changed files with 346 additions and 61 deletions

View File

@@ -107,14 +107,15 @@
a <--> b
b o--o c
c x--x d
a2 --> b2
b2 --o c2
c2 --x d2
a21([In the box]) --> b2
b2((b2)) --o c2
c2(c2) --x d2 --> id1{{This is the text in the box}} --> A[(cylindrical<br />shape<br />test)]
</div>
old:
<div class="mermaid" style="width: 100%; height: 100%">
graph LR
a --> b
a((a)) --> b --> id1{{This is the text in the box}}
A[(cylindrical<br />shape<br />test)]
</div>
</div>

View File

@@ -2,11 +2,11 @@
* Borrowed with love from from dagrge-d3. Many thanks to cpettitt!
*/
import node from './intersect-node';
import circle from './intersect-circle';
import ellipse from './intersect-ellipse';
import polygon from './intersect-polygon';
import rect from './intersect-rect';
import node from './intersect-node.js';
import circle from './intersect-circle.js';
import ellipse from './intersect-ellipse.js';
import polygon from './intersect-polygon.js';
import rect from './intersect-rect.js';
export default {
node,

View File

@@ -1,17 +1,14 @@
import intersectRect from './intersect/intersect-rect';
import intersect from './intersect/index.js';
import { logger } from '../logger'; // eslint-disable-line
import createLabel from './createLabel';
const rect = (parent, node) => {
const labelHelper = (parent, node) => {
// Add outer g element
const shapeSvg = parent
.insert('g')
.attr('class', 'node default')
.attr('id', node.id);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');
// Create the label and insert it after the rect
const label = shapeSvg.insert('g').attr('class', 'label');
@@ -22,7 +19,279 @@ const rect = (parent, node) => {
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
.attr('rx', node.rx)
.attr('ry', node.ry)
@@ -31,21 +300,74 @@ const rect = (parent, node) => {
.attr('width', bbox.width + node.padding)
.attr('height', bbox.height + node.padding);
// Center the label
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
const rectBox = rect.node().getBBox();
node.width = rectBox.width;
node.height = rectBox.height;
updateNodeBounds(node, rect);
node.intersect = function(point) {
return intersectRect(node, point);
return intersect.rect(node, point);
};
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 = {};

View File

@@ -329,44 +329,6 @@ export const draw = function(text, id) {
// Add custom shapes
// 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.
const svg = d3.select(`[id="${id}"]`);