linusz 2019-06-30
首先在body外插入一个absolute的容器避免重绘:
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);
总结出了两种方法,这里由于我使用的是svg,其他元素同理。下面先说性能最好的一个方法,先创建所有的text元素,然后统一append到准备好的容器里。
代码如下:
export function getSvgsWidth(texts) { // 这里使用div不用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; } // 得到1-1000000数字在屏幕上的宽度 console.log(getSvgsWidth([...Array(100000).keys()]));
还有一个方法(不推荐)就是事先准备好一个text,然后每次替换里面的textContent返回宽度,代码如下:
// 准备好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; }
// 可以做一个性能测试,我这边算出来他俩一直保持着5倍左右的差距 const dateStart = new Date().getTime(); console.log(getSvgsWidth([...Array(100000).keys()])); console.log(getSvgsWidthWithOneText([...Array(100000).keys()])); console.log(new Date().getTime() - dateStart);