71
72
// usage creates any necessary tags for actually using the service in the SVG.
72
73
func (s *service) usage(canvas *svg.SVG, iconIds map[string]string) {
74
canvas.Group(fmt.Sprintf(`transform="translate(%d,%d)"`, s.point.X, s.point.Y))
81
`class="service-block" fill="#f5f5f5" stroke="#888" stroke-width="1"`)
83
serviceBlockSize/2-iconSize/2+5, // for these two, add an offset to help
84
serviceBlockSize/2-iconSize/2+7, // hide the embossed border.
86
`id="service-icon-mask-`+s.name+`" fill="none"`)
87
canvas.ClipPath(`id="clip-` + s.name + `"`)
77
fmt.Sprintf(`id=%q`, s.name))
91
`#service-icon-mask-`+s.name)
78
93
if len(s.iconSrc) > 0 {
80
s.point.X+serviceBlockSize/2-iconSize/2,
81
s.point.Y+serviceBlockSize/2-iconSize/2,
82
97
"#"+iconIds[s.charmPath],
83
fmt.Sprintf(`width="%d" height="%d"`, iconSize, iconSize),
98
fmt.Sprintf(`transform="translate(%d,%d)" width="%d" height="%d" clip-path="url(#clip-%s)"`, serviceBlockSize/2-iconSize/2, serviceBlockSize/2-iconSize/2, iconSize, iconSize, s.name),
87
s.point.X+serviceBlockSize/2-iconSize/2,
88
s.point.Y+serviceBlockSize/2-iconSize/2,
102
serviceBlockSize/2-iconSize/2,
103
serviceBlockSize/2-iconSize/2,
107
`clip-path="url(#clip-`+s.name+`)"`,
95
s.point.X+serviceBlockSize/2,
96
s.point.Y+serviceBlockSize/6,
112
name = fmt.Sprintf("%s...", name[:17])
119
`rx="2" ry="2" fill="rgba(220, 220, 220, 0.8)"`)
124
`text-anchor="middle" style="font-weight:200"`)
104
127
// definition creates any necessary defs that can be used later in the SVG.
108
131
// usage creates any necessary tags for actually using the relation in the SVG.
109
132
func (r *serviceRelation) usage(canvas *svg.SVG) {
110
l := r.shortestRelation()
137
p0: r.serviceA.point.Add(point(serviceBlockSize/2, serviceBlockSize/2)),
138
p1: r.serviceB.point.Add(point(serviceBlockSize/2, serviceBlockSize/2)),
120
149
mid := l.p0.Add(l.p1).Div(2).Sub(point(healthCircleRadius, healthCircleRadius))
121
150
canvas.Use(mid.X, mid.Y, "#healthCircle")
124
// shortestRelation finds the shortest line between two services, assuming
125
// that each service can be connected on one of four cardinal points only.
126
func (r *serviceRelation) shortestRelation() line {
127
aConnectors, bConnectors := r.serviceA.cardinalPoints(), r.serviceB.cardinalPoints()
128
shortestDistance := float64(maxInt)
129
shortestPair := line{
130
p0: r.serviceA.point,
131
p1: r.serviceB.point,
133
for _, pointA := range aConnectors {
134
for _, pointB := range bConnectors {
135
ab := line{p0: pointA, p1: pointB}
136
distance := ab.length()
137
if distance < shortestDistance {
138
shortestDistance = distance
146
// cardinalPoints generates the points for each of the four cardinal points
148
func (s *service) cardinalPoints() []image.Point {
149
return []image.Point{
150
point(s.point.X+serviceBlockSize/2, s.point.Y),
151
point(s.point.X, s.point.Y+serviceBlockSize/2),
152
point(s.point.X+serviceBlockSize/2, s.point.Y+serviceBlockSize),
153
point(s.point.X+serviceBlockSize, s.point.Y+serviceBlockSize/2),
152
deg := math.Atan2(float64(l.p0.Y-l.p1.Y), float64(l.p0.X-l.p1.X))
154
int(float64(l.p0.X)-math.Cos(deg)*(serviceBlockSize/2)),
155
int(float64(l.p0.Y)-math.Sin(deg)*(serviceBlockSize/2)),
157
fmt.Sprintf(`fill=%q`, relationColor))
159
int(float64(l.p1.X)+math.Cos(deg)*(serviceBlockSize/2)),
160
int(float64(l.p1.Y)+math.Sin(deg)*(serviceBlockSize/2)),
162
fmt.Sprintf(`fill=%q`, relationColor))
157
165
// strokeDashArray generates the stroke-dasharray attribute content so that
201
209
for _, service := range c.services {
202
210
service.point = service.point.Sub(point(minWidth, minHeight))
204
return abs(maxWidth-minWidth) + serviceBlockSize,
205
abs(maxHeight-minHeight) + serviceBlockSize
212
return abs(maxWidth-minWidth) + serviceBlockSize + 1,
213
abs(maxHeight-minHeight) + serviceBlockSize + 1
208
216
func (c *Canvas) definition(canvas *svg.SVG) {
210
218
defer canvas.DefEnd()
213
canvas.Group(`id="serviceBlock"`,
214
`transform="scale(0.8)"`)
215
io.WriteString(canvas.Writer, assets.ServiceModule)
218
220
// Relation health circle.
219
canvas.Gid("healthCircle")
224
fmt.Sprintf("stroke:%s;fill:none;stroke-width:%dpx", relationColor, relationLineWidth),
229
healthCircleRadius/2,
230
fmt.Sprintf("fill:%s", relationColor),
221
canvas.Group(`id="healthCircle"`,
222
`transform="scale(1.1)"`)
223
io.WriteString(canvas.Writer, assets.RelationIconHealthy)
234
226
// Service and relation specific defs.