constructor(
horizontalAlignment: 'start' | 'middle' | 'end' = 'middle',
verticalAlignment: 'top' | 'center' | 'bottom' = 'center'
) {
super()
this.horizontalAlignment = horizontalAlignment
this.verticalAlignment = verticalAlignment
}
In this step, we will add horizontal and vertical text alignment support to the label style.
First, we add a constructor with properties for both options.
constructor(
horizontalAlignment: 'start' | 'middle' | 'end' = 'middle',
verticalAlignment: 'top' | 'center' | 'bottom' = 'center'
) {
super()
this.horizontalAlignment = horizontalAlignment
this.verticalAlignment = verticalAlignment
}
We’ll introduce an updateText method that updates the text
element’s text content and alignment and can be used in
createVisual and
updateVisual.
private updateText(
textElement: SVGTextElement,
text: string,
labelSize: Size
): void {
To horizontally align the text, we use the SVG text-anchor attribute. After setting the anchor point of the text, we set the x-value of the translation according to the left, middle or right position of the label layout. This way, we don’t have to measure the text.
textElement.setAttribute('text-anchor', this.horizontalAlignment)
// calculate offset for horizontal alignment
// leave room for the padding
let translateX: number
switch (this.horizontalAlignment) {
case 'start':
// the left border of the label
translateX = padding
break
case 'middle':
// the label center
translateX = labelSize.width * 0.5
break
case 'end':
// the right border of the label
translateX = labelSize.width - padding
break
}
Next, we will vertically align the text. Since SVG <text> does not
support a vertical anchor point, we have to use the measured height to calculate the
vertical offset.
// calculate the size of the text element
const textSize = TextRenderSupport.measureText(textContent, font)
// calculate vertical offset for centered alignment
let translateY: number = (labelSize.height - textSize.height) * 0.5
switch (this.verticalAlignment) {
case 'top':
translateY = padding
break
case 'center':
translateY = (labelSize.height - textSize.height) * 0.5
break
case 'bottom':
translateY = labelSize.height - textSize.height - padding
break
}
|
Note
|
Measuring text can be very costly, especially if a lot of text elements have to be measured frequently. Therefore, it should be used as little as possible. In this style, the text is only measured if the label size or text, or the alignment changes. |