diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 2ff96d2eb..2b48d70ef 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -461,8 +461,12 @@ func drawConnection(writer io.Writer, labelMaskID string, connection d2target.Co } fmt.Fprintf(writer, out) } else { - fmt.Fprintf(writer, ``, - path, connectionStyle(connection), attrs) + animatedClass := "" + if connection.Animated { + animatedClass = " animated-connection" + } + fmt.Fprintf(writer, ``, + path, animatedClass, connectionStyle(connection), attrs) } if connection.Label != "" { @@ -968,11 +972,14 @@ func connectionStyle(connection d2target.Connection) string { out += fmt.Sprintf(`stroke:%s;`, connection.Stroke) out += fmt.Sprintf(`opacity:%f;`, connection.Opacity) out += fmt.Sprintf(`stroke-width:%d;`, connection.StrokeWidth) - if connection.StrokeDash != 0 { - dashSize, gapSize := svg.GetStrokeDashAttributes(float64(connection.StrokeWidth), connection.StrokeDash) + strokeDash := connection.StrokeDash + if strokeDash == 0 && connection.Animated { + strokeDash = 5 + } + if strokeDash != 0 { + dashSize, gapSize := svg.GetStrokeDashAttributes(float64(connection.StrokeWidth), strokeDash) out += fmt.Sprintf(`stroke-dasharray:%f,%f;`, dashSize, gapSize) } - return out } @@ -1015,6 +1022,27 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) { } } + triggers = []string{ + `animated-connection`, + } + + for _, t := range triggers { + if strings.Contains(content, t) { + buf.WriteString(` +@keyframes dashdraw { + from { + stroke-dashoffset: 30; + } +} + +.animated-connection { + stroke-dasharray: 15 15; + animation: dashdraw 0.5s linear infinite; +}`) + break + } + } + triggers = []string{ `appendix-icon`, } diff --git a/d2renderers/d2svg/style.css b/d2renderers/d2svg/style.css index 5a7bc3b10..2476c6ae7 100644 --- a/d2renderers/d2svg/style.css +++ b/d2renderers/d2svg/style.css @@ -10,15 +10,3 @@ mix-blend-mode: multiply; opacity: 0.5; } - - -@keyframes dashdraw { - from { - stroke-dashoffset: 30; - } -} - -path[stroke-dasharray] { - stroke-dasharray: 15 15; - animation: dashdraw 0.5s linear infinite; -} diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index a8acc138a..f9b064710 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -1764,6 +1764,13 @@ e <--> f: { } }`, }, + { + name: "animated", + script: ` +your love life will be -> happy: { style.animated: true } +your love life will be -> harmonious: { style.animated: true } +`, + }, } runa(t, tcs) diff --git a/e2etests/testdata/regression/dagre_edge_label_spacing/dagre/sketch.exp.svg b/e2etests/testdata/regression/dagre_edge_label_spacing/dagre/sketch.exp.svg index 24918268a..1e7b73085 100644 --- a/e2etests/testdata/regression/dagre_edge_label_spacing/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/dagre_edge_label_spacing/dagre/sketch.exp.svg @@ -18,18 +18,6 @@ width="2832" height="441" viewBox="-102 -102 2832 441">your love life will behappyharmonious + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/animated/elk/board.exp.json b/e2etests/testdata/stable/animated/elk/board.exp.json new file mode 100644 index 000000000..89d3c0453 --- /dev/null +++ b/e2etests/testdata/stable/animated/elk/board.exp.json @@ -0,0 +1,214 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "your love life will be", + "type": "", + "pos": { + "x": 111, + "y": 12 + }, + "width": 247, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "your love life will be", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 147, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "happy", + "type": "", + "pos": { + "x": 12, + "y": 238 + }, + "width": 149, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "happy", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 49, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "harmonious", + "type": "", + "pos": { + "x": 181, + "y": 238 + }, + "width": 190, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "harmonious", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 90, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(your love life will be -> happy)[0]", + "src": "your love life will be", + "srcArrow": "none", + "srcLabel": "", + "dst": "happy", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 193.66666666666669, + "y": 138 + }, + { + "x": 193.66666666666669, + "y": 188 + }, + { + "x": 86.5, + "y": 188 + }, + { + "x": 86.5, + "y": 238 + } + ], + "animated": true, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(your love life will be -> harmonious)[0]", + "src": "your love life will be", + "srcArrow": "none", + "srcLabel": "", + "dst": "harmonious", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 276, + "y": 138 + }, + { + "x": 276, + "y": 238 + } + ], + "animated": true, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/animated/elk/sketch.exp.svg b/e2etests/testdata/stable/animated/elk/sketch.exp.svg new file mode 100644 index 000000000..6adb4db90 --- /dev/null +++ b/e2etests/testdata/stable/animated/elk/sketch.exp.svg @@ -0,0 +1,62 @@ + +your love life will behappyharmonious + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg index 048039058..90796e221 100644 --- a/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg @@ -18,18 +18,6 @@ width="494" height="793" viewBox="-108 -107 494 793">