Merge pull request #634 from Paracelsus-Rose/master
d2renderer: #579 Circle Arrowhead
This commit is contained in:
commit
a1bebb8b23
8 changed files with 704 additions and 0 deletions
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#### Features 🚀
|
||||
|
||||
- Circle arrowheads are now supported. [#634](https://github.com/terrastruct/d2/pull/634)
|
||||
|
||||
- `animated` keyword implemented for connections. [#652](https://github.com/terrastruct/d2/pull/652)
|
||||
- `border-radius` keyword implemented for squares/rectangles. [#688](https://github.com/terrastruct/d2/pull/688)
|
||||
|
||||
|
|
|
|||
|
|
@ -111,6 +111,9 @@ func arrowheadDimensions(arrowhead d2target.Arrowhead, strokeWidth float64) (wid
|
|||
case d2target.DiamondArrowhead:
|
||||
widthMultiplier = 11
|
||||
heightMultiplier = 9
|
||||
case d2target.FilledCircleArrowhead, d2target.CircleArrowhead:
|
||||
widthMultiplier = 12
|
||||
heightMultiplier = 12
|
||||
case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired:
|
||||
widthMultiplier = 14
|
||||
heightMultiplier = 15
|
||||
|
|
@ -221,6 +224,43 @@ func arrowheadMarker(isTarget bool, id string, connection d2target.Connection) s
|
|||
width*0.6, height*7/8,
|
||||
)
|
||||
}
|
||||
case d2target.FilledCircleArrowhead:
|
||||
attrs := fmt.Sprintf(`class="connection" fill="%s" stroke-width="%d"`, connection.Stroke, connection.StrokeWidth)
|
||||
radius := width / 2
|
||||
if isTarget {
|
||||
path = fmt.Sprintf(`<circle %s cx="%f" cy="%f" r="%f"/>`,
|
||||
attrs,
|
||||
radius+strokeWidth/2,
|
||||
radius,
|
||||
radius-strokeWidth/2,
|
||||
)
|
||||
} else {
|
||||
path = fmt.Sprintf(`<circle %s cx="%f" cy="%f" r="%f"/>`,
|
||||
attrs,
|
||||
radius-strokeWidth/2,
|
||||
radius,
|
||||
radius-strokeWidth/2,
|
||||
)
|
||||
}
|
||||
case d2target.CircleArrowhead:
|
||||
attrs := fmt.Sprintf(`class="connection" fill="white" stroke="%s" stroke-width="%d"`, connection.Stroke, connection.StrokeWidth)
|
||||
radius := width / 2
|
||||
if isTarget {
|
||||
path = fmt.Sprintf(`<circle %s cx="%f" cy="%f" r="%f"/>`,
|
||||
attrs,
|
||||
radius+strokeWidth/2,
|
||||
radius,
|
||||
radius-strokeWidth,
|
||||
)
|
||||
} else {
|
||||
path = fmt.Sprintf(`<circle %s cx="%f" cy="%f" r="%f"/>`,
|
||||
attrs,
|
||||
radius-strokeWidth/2,
|
||||
radius,
|
||||
radius-strokeWidth,
|
||||
)
|
||||
}
|
||||
|
||||
case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired:
|
||||
attrs := fmt.Sprintf(`class="connection" stroke="%s" stroke-width="%d" fill="white"`, connection.Stroke, connection.StrokeWidth)
|
||||
offset := 4.0 + float64(connection.StrokeWidth*2)
|
||||
|
|
|
|||
|
|
@ -340,6 +340,8 @@ const (
|
|||
TriangleArrowhead Arrowhead = "triangle"
|
||||
DiamondArrowhead Arrowhead = "diamond"
|
||||
FilledDiamondArrowhead Arrowhead = "filled-diamond"
|
||||
CircleArrowhead Arrowhead = "circle"
|
||||
FilledCircleArrowhead Arrowhead = "filled-circle"
|
||||
|
||||
// For fat arrows
|
||||
LineArrowhead Arrowhead = "line"
|
||||
|
|
@ -357,6 +359,8 @@ var Arrowheads = map[string]struct{}{
|
|||
string(TriangleArrowhead): {},
|
||||
string(DiamondArrowhead): {},
|
||||
string(FilledDiamondArrowhead): {},
|
||||
string(CircleArrowhead): {},
|
||||
string(FilledCircleArrowhead): {},
|
||||
string(CfOne): {},
|
||||
string(CfMany): {},
|
||||
string(CfOneRequired): {},
|
||||
|
|
@ -370,6 +374,11 @@ func ToArrowhead(arrowheadType string, filled bool) Arrowhead {
|
|||
return FilledDiamondArrowhead
|
||||
}
|
||||
return DiamondArrowhead
|
||||
case string(CircleArrowhead):
|
||||
if filled {
|
||||
return FilledCircleArrowhead
|
||||
}
|
||||
return CircleArrowhead
|
||||
case string(ArrowArrowhead):
|
||||
return ArrowArrowhead
|
||||
case string(CfOne):
|
||||
|
|
|
|||
|
|
@ -1762,6 +1762,29 @@ e <--> f: {
|
|||
target-arrowhead: {
|
||||
shape: cf-one-required
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "circle_arrowhead",
|
||||
script: `
|
||||
a <-> b: circle {
|
||||
source-arrowhead: {
|
||||
shape: circle
|
||||
}
|
||||
target-arrowhead: {
|
||||
shape: circle
|
||||
}
|
||||
}
|
||||
|
||||
c <-> d: filled-circle {
|
||||
source-arrowhead: {
|
||||
shape: circle
|
||||
style.filled: true
|
||||
}
|
||||
target-arrowhead: {
|
||||
shape: circle
|
||||
style.filled: true
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
264
e2etests/testdata/stable/circle_arrowhead/dagre/board.exp.json
generated
vendored
Normal file
264
e2etests/testdata/stable/circle_arrowhead/dagre/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
{
|
||||
"name": "",
|
||||
"fontFamily": "SourceSansPro",
|
||||
"shapes": [
|
||||
{
|
||||
"id": "a",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"width": 113,
|
||||
"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": "a",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 0,
|
||||
"y": 247
|
||||
},
|
||||
"width": 113,
|
||||
"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": "b",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 174,
|
||||
"y": 0
|
||||
},
|
||||
"width": 113,
|
||||
"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": "c",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 173,
|
||||
"y": 247
|
||||
},
|
||||
"width": 114,
|
||||
"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": "d",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 14,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"id": "(a <-> b)[0]",
|
||||
"src": "a",
|
||||
"srcArrow": "circle",
|
||||
"srcLabel": "",
|
||||
"dst": "b",
|
||||
"dstArrow": "circle",
|
||||
"dstLabel": "",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "#0D32B2",
|
||||
"label": "circle",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#676C7E",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 36,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 56.5,
|
||||
"y": 126
|
||||
},
|
||||
{
|
||||
"x": 56.5,
|
||||
"y": 174.4
|
||||
},
|
||||
{
|
||||
"x": 56.5,
|
||||
"y": 198.7
|
||||
},
|
||||
{
|
||||
"x": 56.5,
|
||||
"y": 247.5
|
||||
}
|
||||
],
|
||||
"isCurve": true,
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
},
|
||||
{
|
||||
"id": "(c <-> d)[0]",
|
||||
"src": "c",
|
||||
"srcArrow": "filled-circle",
|
||||
"srcLabel": "",
|
||||
"dst": "d",
|
||||
"dstArrow": "filled-circle",
|
||||
"dstLabel": "",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "#0D32B2",
|
||||
"label": "filled-circle",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#676C7E",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 73,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 230,
|
||||
"y": 126
|
||||
},
|
||||
{
|
||||
"x": 230,
|
||||
"y": 174.4
|
||||
},
|
||||
{
|
||||
"x": 230,
|
||||
"y": 198.7
|
||||
},
|
||||
{
|
||||
"x": 230,
|
||||
"y": 247.5
|
||||
}
|
||||
],
|
||||
"isCurve": true,
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
60
e2etests/testdata/stable/circle_arrowhead/dagre/sketch.exp.svg
vendored
Normal file
60
e2etests/testdata/stable/circle_arrowhead/dagre/sketch.exp.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 470 KiB |
246
e2etests/testdata/stable/circle_arrowhead/elk/board.exp.json
generated
vendored
Normal file
246
e2etests/testdata/stable/circle_arrowhead/elk/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
{
|
||||
"name": "",
|
||||
"fontFamily": "SourceSansPro",
|
||||
"shapes": [
|
||||
{
|
||||
"id": "a",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 12,
|
||||
"y": 12
|
||||
},
|
||||
"width": 113,
|
||||
"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": "a",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 12,
|
||||
"y": 359
|
||||
},
|
||||
"width": 113,
|
||||
"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": "b",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 145,
|
||||
"y": 12
|
||||
},
|
||||
"width": 113,
|
||||
"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": "c",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 13,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 145,
|
||||
"y": 359
|
||||
},
|
||||
"width": 114,
|
||||
"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": "d",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#0A0F25",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 14,
|
||||
"labelHeight": 26,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"id": "(a <-> b)[0]",
|
||||
"src": "a",
|
||||
"srcArrow": "circle",
|
||||
"srcLabel": "",
|
||||
"dst": "b",
|
||||
"dstArrow": "circle",
|
||||
"dstLabel": "",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "#0D32B2",
|
||||
"label": "circle",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#676C7E",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 36,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 68.5,
|
||||
"y": 138
|
||||
},
|
||||
{
|
||||
"x": 68.5,
|
||||
"y": 359
|
||||
}
|
||||
],
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
},
|
||||
{
|
||||
"id": "(c <-> d)[0]",
|
||||
"src": "c",
|
||||
"srcArrow": "filled-circle",
|
||||
"srcLabel": "",
|
||||
"dst": "d",
|
||||
"dstArrow": "filled-circle",
|
||||
"dstLabel": "",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "#0D32B2",
|
||||
"label": "filled-circle",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "#676C7E",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 73,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 202,
|
||||
"y": 138
|
||||
},
|
||||
{
|
||||
"x": 202,
|
||||
"y": 359
|
||||
}
|
||||
],
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
60
e2etests/testdata/stable/circle_arrowhead/elk/sketch.exp.svg
vendored
Normal file
60
e2etests/testdata/stable/circle_arrowhead/elk/sketch.exp.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 470 KiB |
Loading…
Reference in a new issue