如何将 svg 文本元素垂直居中?

问题描述 投票:0回答:1

在下面的代码中,我能够通过反复试验确定

yOffset
值。

我更愿意计算该值,以便文本垂直居中。

我怎样才能做到这一点?

SVG Text元素的文档说:

文本基线起点的y坐标,或者y 如果提供了值列表,则为每个单独字形的坐标。 值类型: (|) 列表;默认值:0; 可动画:是

因此,我需要能够确定一般性地解决这个问题的基线是什么。我怎样才能做到这一点?

function measureSVGText(text, fontSize, fontFamily) {
  // Create an offscreen SVG element
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  
  svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  svg.setAttribute("width", "0");
  svg.setAttribute("height", "0");
  svg.style.position = "absolute";
  svg.style.top = "-9999px";
  svg.style.left = "-9999px";

  // Create a text element
  const textElement = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "text"
  );
  
  textElement.setAttribute("x", "0");
  textElement.setAttribute("y", "0");
  textElement.style.fontSize = fontSize;
  textElement.style.fontFamily = fontFamily;
  textElement.textContent = text;

  // Append the text element to the SVG
  svg.appendChild(textElement);
  document.body.appendChild(svg);

  // Get the bounding box of the text element
  const bbox = textElement.getBBox();
  const roundedBBox = svg.createSVGRect();

  roundedBBox.width = Math.ceil(bbox.width);
  roundedBBox.height = Math.ceil(bbox.height);

  // Remove the SVG element from the DOM
  document.body.removeChild(svg);

  return roundedBBox;
}

function createSVGLabel(text) {
  const padding = 4;
  const fontSize = 10;
  const fontFamily = "Roboto";
  const bbox = measureSVGText(text, `${fontSize}px`, fontFamily);

  const svgWidth = bbox.width + padding * 2;
  const svgHeight = bbox.height + padding * 2;
  const yOffset = 13;
  
  const svg =
    '<?xml version="1.0"?>' +
    `<svg width="${svgWidth}" height="${svgHeight}" viewBox="0 0 ${svgWidth} ${svgHeight}" version="1.1" xmlns="http://www.w3.org/2000/svg">` +
    `<rect width="${svgWidth}" height="${svgHeight}" rx="10" ry="10" style="fill:white" />` +
    `<text x="4" y="${yOffset}" font-family="${fontFamily}" font-size="${fontSize}" fill="black">${text}</text>` +
    "</svg>";

  return svg;
}

const label = createSVGLabel("00000");

const parser = new DOMParser();
const labelDocument = parser.parseFromString(label, "image/svg+xml");
const labelNode = labelDocument.getElementsByTagName("svg")[0];
const container = document.getElementById("container");

container.appendChild(labelNode);
<div id="container" style="width: 200px; height: 200px; background-color: black;">
</div>

svg dom
1个回答
0
投票

只需设置dominant-baseline =“central”

function measureSVGText(text, fontSize, fontFamily) {
  // Create an offscreen SVG element
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  
  svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  svg.setAttribute("width", "0");
  svg.setAttribute("height", "0");
  svg.style.position = "absolute";
  svg.style.top = "-9999px";
  svg.style.left = "-9999px";

  // Create a text element
  const textElement = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "text"
  );
  
  textElement.setAttribute("x", "0");
  textElement.setAttribute("y", "0");
  textElement.style.fontSize = fontSize;
  textElement.style.fontFamily = fontFamily;
  textElement.textContent = text;

  // Append the text element to the SVG
  svg.appendChild(textElement);
  document.body.appendChild(svg);

  // Get the bounding box of the text element
  const bbox = textElement.getBBox();
  const roundedBBox = svg.createSVGRect();

  roundedBBox.width = Math.ceil(bbox.width);
  roundedBBox.height = Math.ceil(bbox.height);

  // Remove the SVG element from the DOM
  document.body.removeChild(svg);

  return roundedBBox;
}

function createSVGLabel(text) {
  const padding = 4;
  const fontSize = 10;
  const fontFamily = "Roboto";
  const bbox = measureSVGText(text, `${fontSize}px`, fontFamily);

  const svgWidth = bbox.width + padding * 2;
  const svgHeight = bbox.height + padding * 2;
  
  const svg =
    '<?xml version="1.0"?>' +
    `<svg width="${svgWidth}" height="${svgHeight}" viewBox="0 0 ${svgWidth} ${svgHeight}" version="1.1" xmlns="http://www.w3.org/2000/svg">` +
    `<rect width="${svgWidth}" height="${svgHeight}" rx="10" ry="10" style="fill:white" />` +
    `<text x="4" y="${svgHeight / 2}" font-family="${fontFamily}" font-size="${fontSize}" fill="black" dominant-baseline="central">${text}</text>` +
    "</svg>";

  return svg;
}

const label = createSVGLabel("00000");

const parser = new DOMParser();
const labelDocument = parser.parseFromString(label, "image/svg+xml");
const labelNode = labelDocument.getElementsByTagName("svg")[0];
const container = document.getElementById("container");

container.appendChild(labelNode);
<div id="container" style="width: 200px; height: 200px; background-color: black;">
</div>

© www.soinside.com 2019 - 2024. All rights reserved.