#1295 Markers implmented, the gereric pattern and diagram specific for flowcharts.

This commit is contained in:
Knut Sveidqvist 2020-03-16 07:55:02 +01:00
parent 5b74d75011
commit 215e930da4
7 changed files with 140 additions and 31 deletions

View File

@ -101,9 +101,20 @@
b-->id1
id1 --> id2
</div>
new:
<div class="mermaid" style="width: 100%; height: 100%">
flowchart LR
a o--o b
a <--> b
b o--o c
c x--x d
a2 --> b2
b2 --o c2
c2 --x d2
</div>
old:
<div class="mermaid" style="width: 100%; height: 100%">
graph LR
a --> b
</div>
</div>

View File

@ -38,6 +38,30 @@ This is set by the renderer of the diagram and insert the data that the wrapper
| padding | Padding. Passed from the renderr as this might differ between react for different diagrams. Maybe obsolete. |
#edge
# edge
arrowType sets the type of arrows to use
arrowType sets the type of arrows to use. The following arrow types are currently supported:
arrow_cross
double_arrow_cross
arrow_point
double_arrow_point
arrow_circle
double_arrow_circle
Lets try to make these types semantic free so that diagram type semantics does not find its way in to this more generic layer.
# Markers
Define what markers that should be included in the diagram with the insert markers function. The function takes two arguments, first the element in which the markers should be included and a list of the markers that should be added.
Ex:
insertMarkers(el, ['point', 'circle'])
The example above adds the markers point and cross. This means that edges with the arrowTypes arrow_cross, double_arrow_cross, arrow_point and double_arrow_cross will get the corresponding markers but arrowType arrow_cross will have no impact.
Current markers:
* point - the standard arrow from flowcharts
* circle - Arrows ending with circle
* cross - arrows starting and ending with a cross

View File

@ -191,6 +191,7 @@ export const insertEdge = function(elem, edge, clusterDb) {
.attr('id', edge.id)
.attr('class', 'transition');
// DEBUG code, adds a red circle at each edge coordinate
// edge.points.forEach(point => {
// elem
// .append('circle')
@ -212,13 +213,29 @@ export const insertEdge = function(elem, edge, clusterDb) {
url = url.replace(/\(/g, '\\(');
url = url.replace(/\)/g, '\\)');
}
logger.info('arrowType', edge.arrowType);
switch (edge.arrowType) {
case 'double_arrow_circle':
svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
svgPath.attr('marker-start', 'url(' + url + '#' + 'circleStart' + ')');
case 'arrow_cross':
svgPath.attr('marker-end', 'url(' + url + '#' + 'crossEnd' + ')');
break;
case 'double_arrow_cross':
svgPath.attr('marker-end', 'url(' + url + '#' + 'crossEnd' + ')');
svgPath.attr('marker-start', 'url(' + url + '#' + 'crossStart' + ')');
break;
case 'arrow_point':
svgPath.attr('marker-end', 'url(' + url + '#' + 'pointEnd' + ')');
break;
case 'double_arrow_point':
svgPath.attr('marker-end', 'url(' + url + '#' + 'pointEnd' + ')');
svgPath.attr('marker-start', 'url(' + url + '#' + 'pointStart' + ')');
break;
case 'arrow_circle':
svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
break;
case 'double_arrow_circle':
svgPath.attr('marker-end', 'url(' + url + '#' + 'circleEnd' + ')');
svgPath.attr('marker-start', 'url(' + url + '#' + 'circleStart' + ')');
break;
default:
}
};

View File

@ -12,8 +12,8 @@ const translateClusterId = id => {
return id;
};
export const render = (elem, graph) => {
insertMarkers(elem);
export const render = (elem, graph, markers) => {
insertMarkers(elem, markers);
clusterDb = {};
clearNodes();
clearEdges();

View File

@ -1,7 +1,14 @@
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*/
const insertMarkers = elem => {
// Only add the number of markers that the diagram needs
const insertMarkers = (elem, markerArray) => {
markerArray.forEach(markerName => {
markers[markerName](elem);
});
};
const extension = elem => {
elem
.append('defs')
.append('marker')
@ -26,7 +33,9 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 1,1 V 13 L18,7 Z'); // this is actual shape for arrowhead
};
const composition = elem => {
elem
.append('defs')
.append('marker')
@ -51,7 +60,8 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
};
const aggregation = elem => {
elem
.append('defs')
.append('marker')
@ -76,7 +86,8 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
};
const dependency = elem => {
elem
.append('defs')
.append('marker')
@ -101,16 +112,17 @@ const insertMarkers = elem => {
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
};
const point = elem => {
elem
.append('marker')
.attr('id', 'normalEnd')
.attr('id', 'pointEnd')
.attr('viewBox', '0 0 10 10')
.attr('refX', 9)
.attr('refX', 10)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
@ -119,24 +131,26 @@ const insertMarkers = elem => {
.style('stroke-dasharray', '1,0');
elem
.append('marker')
.attr('id', 'normalStart')
.attr('id', 'pointStart')
.attr('viewBox', '0 0 10 10')
.attr('refX', 9)
.attr('refX', 0)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
.attr('d', 'M 0 5 L 10 10 L 10 0 z')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
};
const circle = elem => {
elem
.append('marker')
.attr('id', 'circleEnd')
.attr('viewBox', '0 0 10 10')
.attr('refX', 10)
.attr('refX', 11)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
@ -146,7 +160,6 @@ const insertMarkers = elem => {
.attr('cx', '5')
.attr('cy', '5')
.attr('r', '5')
.attr('fill', 'red')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
@ -155,7 +168,7 @@ const insertMarkers = elem => {
.append('marker')
.attr('id', 'circleStart')
.attr('viewBox', '0 0 10 10')
.attr('refX', 0)
.attr('refX', -1)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
@ -165,10 +178,54 @@ const insertMarkers = elem => {
.attr('cx', '5')
.attr('cy', '5')
.attr('r', '5')
.attr('fill', 'red')
.attr('class', 'arrowheadPath')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0');
};
const cross = elem => {
elem
.append('marker')
.attr('id', 'crossEnd')
.attr('viewBox', '0 0 11 11')
.attr('refX', 12)
.attr('refY', 5.2)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('orient', 'auto')
.append('path')
.attr('stroke', 'black')
.attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
.attr('class', 'arrowheadPath')
.style('stroke-width', 2)
.style('stroke-dasharray', '1,0');
elem
.append('marker')
.attr('id', 'crossStart')
.attr('viewBox', '0 0 11 11')
.attr('refX', -1)
.attr('refY', 5.2)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 7)
.attr('markerHeight', 7)
.attr('orient', 'auto')
.append('path')
.attr('stroke', 'black')
.attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9')
.attr('class', 'arrowheadPath')
.style('stroke-width', 2)
.style('stroke-dasharray', '1,0');
};
// TODO rename the class diagram markers to something shape descriptive and semanitc free
const markers = {
extension,
composition,
aggregation,
dependency,
point,
circle,
cross
};
export default insertMarkers;

View File

@ -496,19 +496,19 @@ const destructStartLink = _str => {
switch (str) {
case '<--':
return { type: 'arrow', stroke: 'normal' };
return { type: 'arrow_point', stroke: 'normal' };
case 'x--':
return { type: 'arrow_cross', stroke: 'normal' };
case 'o--':
return { type: 'arrow_circle', stroke: 'normal' };
case '<-.':
return { type: 'arrow', stroke: 'dotted' };
return { type: 'arrow_point', stroke: 'dotted' };
case 'x-.':
return { type: 'arrow_cross', stroke: 'dotted' };
case 'o-.':
return { type: 'arrow_circle', stroke: 'dotted' };
case '<==':
return { type: 'arrow', stroke: 'thick' };
return { type: 'arrow_point', stroke: 'thick' };
case 'x==':
return { type: 'arrow_cross', stroke: 'thick' };
case 'o==':
@ -529,7 +529,7 @@ const destructEndLink = _str => {
case '--x':
return { type: 'arrow_cross', stroke: 'normal' };
case '-->':
return { type: 'arrow', stroke: 'normal' };
return { type: 'arrow_point', stroke: 'normal' };
case '<-->':
return { type: 'double_arrow_point', stroke: 'normal' };
case 'x--x':
@ -561,7 +561,7 @@ const destructEndLink = _str => {
case '-.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '-.->':
return { type: 'arrow', stroke: 'dotted' };
return { type: 'arrow_point', stroke: 'dotted' };
case '-.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '-.-':
@ -569,7 +569,7 @@ const destructEndLink = _str => {
case '.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '.->':
return { type: 'arrow', stroke: 'dotted' };
return { type: 'arrow_point', stroke: 'dotted' };
case '.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '.-':
@ -577,7 +577,7 @@ const destructEndLink = _str => {
case '==x':
return { type: 'arrow_cross', stroke: 'thick' };
case '==>':
return { type: 'arrow', stroke: 'thick' };
return { type: 'arrow_point', stroke: 'thick' };
case '==o':
return { type: 'arrow_circle', stroke: 'thick' };
case '===':

View File

@ -372,7 +372,7 @@ export const draw = function(text, id) {
// Run the renderer. This is what draws the final graph.
const element = d3.select('#' + id + ' g');
render(element, g);
render(element, g, ['point', 'circle', 'cross']);
dagre.layout(g);
element.selectAll('g.node').attr('title', function() {