On js method of calculating the width of non equal width font

Posted by Vizionz on Mon, 02 Dec 2019 02:01:20 +0100

Prepare a container

First, insert an absolute container outside the body to avoid redrawing:

const svgWidthTestContainer = document.createElement('svg');
svgWidthTestContainer.setAttribute('id', 'svgWidthTest');

svgWidthTestContainer.style.cssText = `
  position: absolute;
  width: 500px;
  height: 500px;
  left: -1000px;
  top: -1000px;
  visibility: 'hidden';
`;
document.body.appendChild(svgWidthTestContainer);

computing method

Two methods are summed up. Because I use svg here, other elements are the same. Let's talk about the best performance method. First, create all text elements, and then uniformly append them to the prepared container.
The code is as follows:

export function getSvgsWidth(texts) {
  // It is inconvenient to delete div s without fragment
  const textsFragment = document.createElement('g');
  const textElements = texts.map((text) => {
    const textElement = document.createElement('text');
    textElement.textContent = text;
    textsFragment.appendChild(textElement);
    return textElement;
  });
  svgWidthTestContainer.appendChild(textsFragment);
  const textElementsWidth = textElements.map(element => element.getBoundingClientRect().width);
  svgWidthTestContainer.removeChild(textsFragment);
  return textElementsWidth;
}
// Get the width of 1-1000000 numbers on the screen
console.log(getSvgsWidth([...Array(100000).keys()]));

Another method (not recommended) is to prepare a text in advance, and then replace the textContent to return the width. The code is as follows:

// Ready text
const textElementTest = document.createElement('text');

svgWidthTestContainer.appendChild(textElementTest);

export function getSvgsWidthWithOneText(texts) {
  const textElementsWidth = texts.map((text) => {
    textElementTest.textContent = text;
    return textElementTest.getBoundingClientRect().width;
  });
  return textElementsWidth;
}
// We can do a performance test. I can figure out that they have kept a gap of about 5 times
const dateStart = new Date().getTime();
console.log(getSvgsWidth([...Array(100000).keys()]));
console.log(getSvgsWidthWithOneText([...Array(100000).keys()]));

console.log(new Date().getTime() - dateStart);

Topics: Front-end Fragment