SVGJS Align Rect and Text to Center

29 Views Asked by At

I am using svg.js to create a component that acts as a scorebar. However, I'm having issues with the legend section of the <rect> and <text> elements not sharing the same "middle" alignment.

Misaligned Labelssvg

Code is below. The component allows font family, size, and weight to be adjusted, so the code is attempting to generate the legend color box based on the font size (no tiny box if developer uses 24 point font, for example):

private createLegend(): G {

    const group: G = SVG().group();

    let xPosition: number = 0;
    const yPosition: number = 30;
    this.transformedRanges.forEach((range) => {

      const colorBox: Rect = this.createLegendBox(xPosition, yPosition, range.color);
      xPosition += 15;

      const textBox: Text = this.createLegendText(xPosition, yPosition, range.label || "");

      // this is the line that controls the vertical alignment of the text
      // in relation to the legend color box.

      textBox.attr("dominant-baseline","middle");
      const textBoxBBox : Box = textBox.bbox();
      const textWidth: number = textBoxBBox.width;
      const textHeight : number = textBoxBBox.height;

      colorBox.width(textHeight /2);
      colorBox.height(textHeight / 2);

      xPosition += textWidth + 15;

      group.add(colorBox);
      group.add(textBox);
    });

    // move the legend to the middle, taking into account the width of the legend itself
    group.transform({
      translateX : (this.svgWidth - group.bbox().width ) / 2
    });

    group.addClass("legendbar2");
    return group;
  }

  private createLegendBox(xPosition: number, yPosition: number, color: string): Rect {

    const rect: Rect = SVG().rect(10, 10).fill(color).move(xPosition, yPosition);
    rect.stroke({
      color: "black",
      width: 0.5
    })
    return rect;
  }

  private createLegendText(xPosition: number, yPosition: number, legendText: string): Text {

    const text: Text = SVG()
      .text(legendText)
      .move(xPosition, yPosition);

    text.font({
      weight: this.options?.fontOptions?.weight || "bold",
      size: this.options?.fontOptions?.size || 12,
      family: this.options?.fontOptions?.family || undefined,
      color: this.options?.fontOptions?.color || undefined
    });

    return text;

  }

I've also tried to do this via attaching a CSS class to the generated group (not noted in the code example). I've tried various settings for the vertical align:

.legendbar {
  width: 85%;
  margin: auto;
  vertical-align: text-top;
  display: inline-block;
}  
0

There are 0 best solutions below