Merge pull request #634 from Paracelsus-Rose/master

d2renderer: #579 Circle Arrowhead
This commit is contained in:
Alexander Wang 2023-01-19 17:56:36 -08:00 committed by GitHub
commit a1bebb8b23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 704 additions and 0 deletions

View file

@ -3,6 +3,8 @@
#### Features 🚀 #### 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) - `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) - `border-radius` keyword implemented for squares/rectangles. [#688](https://github.com/terrastruct/d2/pull/688)

View file

@ -111,6 +111,9 @@ func arrowheadDimensions(arrowhead d2target.Arrowhead, strokeWidth float64) (wid
case d2target.DiamondArrowhead: case d2target.DiamondArrowhead:
widthMultiplier = 11 widthMultiplier = 11
heightMultiplier = 9 heightMultiplier = 9
case d2target.FilledCircleArrowhead, d2target.CircleArrowhead:
widthMultiplier = 12
heightMultiplier = 12
case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired: case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired:
widthMultiplier = 14 widthMultiplier = 14
heightMultiplier = 15 heightMultiplier = 15
@ -221,6 +224,43 @@ func arrowheadMarker(isTarget bool, id string, connection d2target.Connection) s
width*0.6, height*7/8, 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: 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) attrs := fmt.Sprintf(`class="connection" stroke="%s" stroke-width="%d" fill="white"`, connection.Stroke, connection.StrokeWidth)
offset := 4.0 + float64(connection.StrokeWidth*2) offset := 4.0 + float64(connection.StrokeWidth*2)

View file

@ -340,6 +340,8 @@ const (
TriangleArrowhead Arrowhead = "triangle" TriangleArrowhead Arrowhead = "triangle"
DiamondArrowhead Arrowhead = "diamond" DiamondArrowhead Arrowhead = "diamond"
FilledDiamondArrowhead Arrowhead = "filled-diamond" FilledDiamondArrowhead Arrowhead = "filled-diamond"
CircleArrowhead Arrowhead = "circle"
FilledCircleArrowhead Arrowhead = "filled-circle"
// For fat arrows // For fat arrows
LineArrowhead Arrowhead = "line" LineArrowhead Arrowhead = "line"
@ -357,6 +359,8 @@ var Arrowheads = map[string]struct{}{
string(TriangleArrowhead): {}, string(TriangleArrowhead): {},
string(DiamondArrowhead): {}, string(DiamondArrowhead): {},
string(FilledDiamondArrowhead): {}, string(FilledDiamondArrowhead): {},
string(CircleArrowhead): {},
string(FilledCircleArrowhead): {},
string(CfOne): {}, string(CfOne): {},
string(CfMany): {}, string(CfMany): {},
string(CfOneRequired): {}, string(CfOneRequired): {},
@ -370,6 +374,11 @@ func ToArrowhead(arrowheadType string, filled bool) Arrowhead {
return FilledDiamondArrowhead return FilledDiamondArrowhead
} }
return DiamondArrowhead return DiamondArrowhead
case string(CircleArrowhead):
if filled {
return FilledCircleArrowhead
}
return CircleArrowhead
case string(ArrowArrowhead): case string(ArrowArrowhead):
return ArrowArrowhead return ArrowArrowhead
case string(CfOne): case string(CfOne):

View file

@ -1762,6 +1762,29 @@ e <--> f: {
target-arrowhead: { target-arrowhead: {
shape: cf-one-required 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
}
}`, }`,
}, },
{ {

View 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
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 470 KiB

View 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
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 470 KiB