mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-15 13:29:40 +02:00
#MC-2558 Handling animations for look neo
This commit is contained in:
@@ -105,11 +105,11 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
AB["apa@apa@"] --> B(("`apa@apa`"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart
|
||||
D(("for D"))
|
||||
</pre>
|
||||
@@ -119,6 +119,208 @@
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==> BB
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: neo
|
||||
look: handDrawn
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==> BB
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
|
||||
<!-- Next set of tests -->
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
slow e2@--> B
|
||||
e2@{ animation: slow}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@--> BB
|
||||
e1@{ animation: fast}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==> BB
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<!-- Circle -->
|
||||
<hr />
|
||||
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==o B
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==o BB
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==o B
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: neo
|
||||
look: handDrawn
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==o BB
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
|
||||
<!-- Next set of tests -->
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
slow e2@--o B
|
||||
e2@{ animation: slow}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@--o BB
|
||||
e1@{ animation: fast}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==o B
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==o BB
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<!-- Cross -->
|
||||
<hr />
|
||||
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==x B
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==x BB
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==x B
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: neo
|
||||
look: handDrawn
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==x BB
|
||||
e1@{ animate: false}
|
||||
</pre>
|
||||
|
||||
<!-- Next set of tests -->
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
slow e2@--x B
|
||||
e2@{ animation: slow}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@--x BB
|
||||
e1@{ animation: fast}
|
||||
</pre>
|
||||
<hr />
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
A e1@==x B
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
theme: forest
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
A e1@==x BB
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
|
||||
|
@@ -781,13 +781,7 @@ export const render = async (
|
||||
const elk = new ELK();
|
||||
const element = svg.select('g');
|
||||
// Add the arrowheads to the svg
|
||||
insertMarkers(
|
||||
element,
|
||||
data4Layout.markers,
|
||||
data4Layout.type,
|
||||
data4Layout.diagramId,
|
||||
data4Layout.config
|
||||
);
|
||||
insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||
|
||||
// Setup the graph with the layout options and the data for the layout
|
||||
let elkGraph: any = {
|
||||
|
@@ -290,13 +290,7 @@ export const render = async (data4Layout, svg) => {
|
||||
return {};
|
||||
});
|
||||
const element = svg.select('g');
|
||||
insertMarkers(
|
||||
element,
|
||||
data4Layout.markers,
|
||||
data4Layout.type,
|
||||
data4Layout.diagramId,
|
||||
data4Layout.config
|
||||
);
|
||||
insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||
clearNodes();
|
||||
clearEdges();
|
||||
clearClusters();
|
||||
|
@@ -94,10 +94,10 @@ export const calcNodeIntersections = async (targetNodeId, _node1, _node2) => {
|
||||
}
|
||||
|
||||
// Insert node will not give any widths as the element is not in the DOM
|
||||
node1.width = _node1.width || 50;
|
||||
node1.height = _node1.height || 50;
|
||||
node2.width = _node2.width || 50;
|
||||
node2.height = _node2.height || 50;
|
||||
node1.width = _node1.width ?? 50;
|
||||
node1.height = _node1.height ?? 50;
|
||||
node2.width = _node2.width ?? 50;
|
||||
node2.height = _node2.height ?? 50;
|
||||
|
||||
const startIntersection = calcIntersectionPoint(node1, { x: node2.x, y: node2.y });
|
||||
const endIntersection = calcIntersectionPoint(node2, { x: node1.x, y: node1.y });
|
||||
@@ -402,13 +402,7 @@ const doRender = async (_elem, data4Layout, siteConfig, positions) => {
|
||||
export const render = async (data4Layout, svg, _internalHelpers, _algorithm, positions) => {
|
||||
const element = svg.select('g');
|
||||
// Org
|
||||
insertMarkers(
|
||||
element,
|
||||
data4Layout.markers,
|
||||
data4Layout.type,
|
||||
data4Layout.diagramId,
|
||||
data4Layout.config
|
||||
);
|
||||
insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||
clearNodes();
|
||||
clearEdges();
|
||||
clearClusters();
|
||||
|
@@ -15,13 +15,14 @@ export const addEdgeMarkers = (
|
||||
edge: Pick<EdgeData, 'arrowTypeStart' | 'arrowTypeEnd'>,
|
||||
url: string,
|
||||
id: string,
|
||||
diagramType: string
|
||||
diagramType: string,
|
||||
useMargin = false
|
||||
) => {
|
||||
if (edge.arrowTypeStart) {
|
||||
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType);
|
||||
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType, useMargin);
|
||||
}
|
||||
if (edge.arrowTypeEnd) {
|
||||
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType);
|
||||
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType, useMargin);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,15 +38,19 @@ const arrowTypesMap = {
|
||||
lollipop: 'lollipop',
|
||||
} as const;
|
||||
|
||||
const arrowTypesWithMarginSupport = ['cross', 'point', 'circle'];
|
||||
|
||||
const addEdgeMarker = (
|
||||
svgPath: SVG,
|
||||
position: 'start' | 'end',
|
||||
arrowType: string,
|
||||
url: string,
|
||||
id: string,
|
||||
diagramType: string
|
||||
diagramType: string,
|
||||
useMargin = false
|
||||
) => {
|
||||
const endMarkerType = arrowTypesMap[arrowType as keyof typeof arrowTypesMap];
|
||||
const marginSupport = arrowTypesWithMarginSupport.includes(endMarkerType);
|
||||
|
||||
if (!endMarkerType) {
|
||||
log.warn(`Unknown arrow type: ${arrowType}`);
|
||||
@@ -53,5 +58,9 @@ const addEdgeMarker = (
|
||||
}
|
||||
|
||||
const suffix = position === 'start' ? 'Start' : 'End';
|
||||
svgPath.attr(`marker-${position}`, `url(${url}#${id}_${diagramType}-${endMarkerType}${suffix})`);
|
||||
const offset = useMargin && marginSupport ? '-margin' : '';
|
||||
svgPath.attr(
|
||||
`marker-${position}`,
|
||||
`url(${url}#${id}_${diagramType}-${endMarkerType}${suffix}${offset})`
|
||||
);
|
||||
};
|
||||
|
@@ -544,7 +544,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
? generateRoundedPath(applyMarkerOffsetsToPoints(lineData, edge), 5)
|
||||
: lineFunction(lineData);
|
||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||
|
||||
let animatedEdge = false;
|
||||
if (edge.look === 'handDrawn') {
|
||||
const rc = rough.svg(elem);
|
||||
Object.assign([], lineData);
|
||||
@@ -592,11 +592,13 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
';' +
|
||||
(edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '')
|
||||
);
|
||||
|
||||
animatedEdge =
|
||||
edge.animate === true || !!edge.animation || stylesFromClasses.includes('animation');
|
||||
const len = svgPath.node().getTotalLength();
|
||||
const oValueS = markerOffsets2[edge.arrowTypeStart] || 0;
|
||||
const oValueE = markerOffsets2[edge.arrowTypeEnd] || 0;
|
||||
|
||||
if (edge.look === 'neo') {
|
||||
if (edge.look === 'neo' && !animatedEdge) {
|
||||
const dashArray = `0 ${oValueS} ${len - oValueS - oValueE} ${oValueE}`;
|
||||
|
||||
// No offset needed because we already start with a zero-length dash that effectively sets us up for a gap at the start.
|
||||
@@ -646,7 +648,9 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
log.info('arrowTypeStart', edge.arrowTypeStart);
|
||||
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
||||
|
||||
addEdgeMarkers(svgPath, edge, url, id, diagramType);
|
||||
const useMargin = !animatedEdge && edge?.look === 'neo';
|
||||
|
||||
addEdgeMarkers(svgPath, edge, url, id, diagramType, useMargin);
|
||||
|
||||
let paths = {};
|
||||
if (pointsHasChanged) {
|
||||
|
@@ -2,9 +2,9 @@
|
||||
import { log } from '../../logger.js';
|
||||
|
||||
// Only add the number of markers that the diagram needs
|
||||
const insertMarkers = (elem, markerArray, type, id, config) => {
|
||||
const insertMarkers = (elem, markerArray, type, id) => {
|
||||
markerArray.forEach((markerName) => {
|
||||
markers[markerName](elem, type, id, config);
|
||||
markers[markerName](elem, type, id);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -153,13 +153,13 @@ const lollipop = (elem, type, id) => {
|
||||
.attr('cy', 7)
|
||||
.attr('r', 6);
|
||||
};
|
||||
const point = (elem, type, id, options) => {
|
||||
const point = (elem, type, id) => {
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-pointEnd')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 11.5 14')
|
||||
.attr('refX', options?.look === 'neo' ? 11.5 : 7.75) // Adjust to position the arrowhead relative to the line
|
||||
.attr('refX', 7.75) // Adjust to position the arrowhead relative to the line
|
||||
.attr('refY', 7) // Half of 14 for vertical center
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 10.5)
|
||||
@@ -175,7 +175,39 @@ const point = (elem, type, id, options) => {
|
||||
.attr('id', id + '_' + type + '-pointStart')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 11.5 14')
|
||||
.attr('refX', options?.look === 'neo' ? 1 : 4)
|
||||
.attr('refX', 4)
|
||||
.attr('refY', 7)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 11.5)
|
||||
.attr('markerHeight', 14)
|
||||
.attr('orient', 'auto')
|
||||
.append('polygon')
|
||||
.attr('points', '0,7 11.5,14 11.5,0')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 0)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-pointEnd-margin')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 11.5 14')
|
||||
.attr('refX', 11.5) // Adjust to position the arrowhead relative to the line
|
||||
.attr('refY', 7) // Half of 14 for vertical center
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 10.5)
|
||||
.attr('markerHeight', 14)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 0 0 L 11.5 7 L 0 14 z')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 0)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-pointStart-margin')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 11.5 14')
|
||||
.attr('refX', 1)
|
||||
.attr('refY', 7)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 11.5)
|
||||
@@ -187,14 +219,14 @@ const point = (elem, type, id, options) => {
|
||||
.style('stroke-width', 0)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
};
|
||||
const circle = (elem, type, id, options) => {
|
||||
const circle = (elem, type, id) => {
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-circleEnd')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refY', 5) // What!!!??
|
||||
.attr('refX', options?.look === 'neo' ? 12.25 : 10.75)
|
||||
.attr('refX', 10.75)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 14)
|
||||
.attr('markerHeight', 14)
|
||||
@@ -212,7 +244,44 @@ const circle = (elem, type, id, options) => {
|
||||
.attr('id', id + '_' + type + '-circleStart')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', options?.look === 'neo' ? -2 : 0)
|
||||
.attr('refX', 0)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 14)
|
||||
.attr('markerHeight', 14)
|
||||
.attr('orient', 'auto')
|
||||
.append('circle')
|
||||
.attr('cx', '5')
|
||||
.attr('cy', '5')
|
||||
.attr('r', '5')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 0)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-circleEnd-margin')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refY', 5) // What!!!??
|
||||
.attr('refX', 12.25)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 14)
|
||||
.attr('markerHeight', 14)
|
||||
.attr('orient', 'auto')
|
||||
.append('circle')
|
||||
.attr('cx', '5')
|
||||
.attr('cy', '5')
|
||||
.attr('r', '5')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 0)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-circleStart-margin')
|
||||
.attr('class', 'marker ' + type)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', -2)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 14)
|
||||
@@ -259,6 +328,38 @@ const cross = (elem, type, id) => {
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 2.5)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-crossEnd-margin')
|
||||
.attr('class', 'marker cross ' + type)
|
||||
.attr('viewBox', '0 0 15 15')
|
||||
.attr('refX', 17.7)
|
||||
.attr('refY', 7.5)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 12)
|
||||
.attr('markerHeight', 12)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 1,1 L 14,14 M 1,14 L 14,1')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 2.5);
|
||||
|
||||
elem
|
||||
.append('marker')
|
||||
.attr('id', id + '_' + type + '-crossStart-margin')
|
||||
.attr('class', 'marker cross ' + type)
|
||||
.attr('viewBox', '0 0 15 15')
|
||||
.attr('refX', -3.5)
|
||||
.attr('refY', 7.5)
|
||||
.attr('markerUnits', 'userSpaceOnUse')
|
||||
.attr('markerWidth', 12)
|
||||
.attr('markerHeight', 12)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 1,1 L 14,14 M 1,14 L 14,1')
|
||||
.attr('class', 'arrowMarkerPath')
|
||||
.style('stroke-width', 2.5)
|
||||
.style('stroke-dasharray', '1,0');
|
||||
};
|
||||
const barb = (elem, type, id) => {
|
||||
elem
|
||||
|
Reference in New Issue
Block a user