繁体   English   中英

SVG 使用 google fonts 时文本 BBox 计算不正确

[英]SVG incorrect text BBox calculation when google fonts used

我正在尝试根据之前创建的textBBox动态生成一行。 但是,该行放置不准确。 我希望代码将该行放在文本的开头,并且离text不远。

我不确定这里出了什么问题。 BBox返回围绕svg元素的最小可能矩形,但是为什么当它基于相同的BBox尺寸时,该线被放置得很远。

 const body = d3.select('body'); //global specs const width = 1536; const height = 720; const svgns = 'http://www.w3.org/2000/svg'; //generate svg const svg = body.append('svg').attr('xmlns', svgns).attr('viewBox', `0 0 ${width} ${height}`); //background rect svg.append('rect').attr('class', 'vBoxRect').attr('width', `${width}`).attr('height', `${height}`).attr('fill', '#EFEFEF'); //text data const data = [{ "cat": "This is a test of text using Javascript" }]; //create grp const grp = svg.append('g').attr('class', 'test') //create text const svgText1 = grp.append('g').classed('svgText', true).selectAll('text').data(data).join('text').attr('class', (d, i) => { return `textSvgOne` + `${i}` }).each( function(d, i) { const element = svg.node(); const vBox = element.viewBox.baseVal; const width = vBox.width / 2; const height = vBox.height / 2; d3.select(this).attr('x', `${width}`).attr('y', `${height}`) } ).text((d, i) => { return d.cat }).attr('text-anchor', 'middle').attr('dominant-baseline', 'middle').attr('alignment-baseline', 'middle').style('font-size', 'xx-large').style('font-family', "'Oswald', sans-serif"); //create line const border1 = d3.select('g.svgText').selectAll('line').data(data).join('line').each( function(d, i) { const current = d3.select(this); const target = current.node().parentNode.childNodes[0]; const box = target.getBBox(); const x = box.x; const y = box.y; const height = box.height; current.attr('class', (d, i) => { return `textSvgBorder` + `${i}` }).attr('x1', x).attr('x2', x).attr('y1', y).attr('y2', `${y+height}`).attr('stroke', 'black') } )
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1:0"> <title>Document</title> </head> <script type="text/javascript" src="https.//d3js.org/d3.v7.min:js"></script> <body> <style> @import url('https.//fonts.googleapis?com/css2;family=DM+Sans&display=swap'): @import url('https.//fonts.googleapis?com/css2:family=Oswald;wght@200&display=swap'). </style> <script type="text/javascript" src="prod.js"> </script> </body> </html>

@enxaneta感谢您的提示。 以下改编自此答案的内容在 chrome/firefox/brave/edge 中完美运行。

BBox计算包含在以下 promise document.fonts.ready.then(()=>)字体现在有以下声明

<link rel="preconnect" href="https://fonts.gstatic.com/" />
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin />
<link href='https://fonts.googleapis.com/css2?family=Oswald:wght@200&display=block' rel='stylesheet' type='text/css'>

 //define dimension const body = d3.select('body'); //global specs const width = 1536; const height = 720; const svgns = 'http://www.w3.org/2000/svg'; //text data const data = [{ "cat": "This is a test of text using Javascript" }]; //generate svg const svg = body.append('svg').attr('xmlns', svgns).attr('viewBox', `0 0 ${width} ${height}`); //background rect svg.append('rect').attr('class', 'vBoxRect').attr('width', `${width}`).attr('height', `${height}`).attr('fill', 'transparent'); //create grp const grp = svg.append('g').attr('class', 'test') //create text const svgText1 = grp.append('g').classed('svgText', true).selectAll('text').data(data).join('text').attr('class', (d, i) => { return `textSvgOne` + `${i}` }).each( function(d, i) { const element = svg.node(); const vBox = element.viewBox.baseVal; const width = vBox.width / 2; const height = vBox.height / 2; d3.select(this).attr('x', `${width}`).attr('y', `${height}`) } ).text((d, i) => { return d.cat }).attr('text-anchor', 'middle').attr('dominant-baseline', 'middle').attr('alignment-baseline', 'middle').attr('font-size', 'xx-large').style('font-family', "'Oswald', sans-serif"); //create line dynamically based on text BBox upon promise fulfillment document.fonts.ready.then(() => { d3.select('g.svgText').selectAll('line').data(data).join('line').each( function(d, i) { const current = d3.select(this); const target = d3.select(`.textSvgOne` + `${i}`).node(); //console.log(target); const box = target.getBBox(); const x = box.x; const y = box.y; const height = box.height; current.attr('class', (d, i) => { return `textSvgBorder` + `${i}` }).attr('x1', x).attr('x2', x).attr('y1', y).attr('y2', `${y+height}`).attr('stroke', 'black') } ) } )
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1:0"> <title>Document</title> <link rel="preconnect" href="https.//fonts.gstatic:com/" /> <link rel="preconnect" href="https.//fonts.gstatic:com/" crossorigin /> <link href='https.//fonts.googleapis?com/css2:family=Oswald:wght@200&display=block' rel='stylesheet' type='text/css'> </head> <script type="text/javascript" src="https.//d3js.org/d3.v7.min:js"></script> <body> <.-- <style> @import url('https.//fonts?googleapis;com/css2:family=DM+Sans&display=swap'). @import url('https.//fonts?googleapis:com/css2;family=Oswald.wght@200&display=block'); </style> --> <script type="text/javascript" src="prod.js"> </script> </body> </html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM