我正在开发一个项目,我必须使用具有给定文本框架宽度和高度的 JavaScript 动态添加 Svg Text 元素,而不会干扰字体比例。我无法做到这一点,请帮助我。
提前致谢
function opacityValue() {
var opValue = document.getElementById("myRange").value;
document.getElementById("opacityValue").textContent = "(" + opValue / 100 + ")";
}
//
function txtOnFloor() {
var color = document.getElementById("clr").value;
var opacity = document.getElementById("myRange").value / 100;
var fontFamily = document.getElementById("family").value;
var svgs = document.getElementById("svgcontent");
var svg = svgs.getElementsByTagName("g")[0];
svg.innerHTML = "";
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
var g2 = document.createElementNS("http://www.w3.org/2000/svg", "g");
var rectNull = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var svgText = document.createElementNS("http://www.w3.org/2000/svg", "text");
var svgTexttemp = document.getElementById("bg_svgtext").value;
var textWidth = svgTexttemp.length;
g.setAttribute("id", "gvr");
var textNode = document.createTextNode("" + svgTexttemp + "");
svgText.appendChild(textNode);
/////
var width1 = parseInt(document.getElementById("w1").value);
var width2 = document.getElementById("w2");
if (width2 != null && width2 != 0) {
width2 = parseInt(width2.value) / 100;
}
else {
width2 = 0;
}
var width = width1 + width2;
var depth1 = parseInt(document.getElementById("d1").value);
var depth2 = document.getElementById("d2");
if (depth2 != null && width2 != 0) {
depth2 = parseInt(width2.value) / 100;
}
else {
depth2 = 0;
}
var depth = depth1 + depth2;
var ratio = width / depth;
//
if (ratio > 1) {
for (var i = 1; i <= 100; i++) {
if (ratio >= i && ratio < i + 1) {
var fSize = (width / textWidth)*i;
svgText.setAttribute("font-size", fSize);
}
}
svgText.setAttribute("textLength", (fSize * textWidth) / ratio);
svgText.setAttribute("lengthAdjust", "spacingAndGlyphs");
}
else if (ratio <= 1) {
svgText.setAttribute("font-size", (width / textWidth)*2.3);
svgText.setAttribute("textLength", width);
svgText.setAttribute("lengthAdjust", "spacingAndGlyphs");
}
//
svgText.setAttribute("fill", "" + color + "");
svgText.setAttribute("opacity", "" + opacity + "");
if (fontFamily == "Fira Bold") {
svgText.setAttribute("font-family", "Fira");
svgText.setAttribute("font-weight", "bold");
}
else if (fontFamily == "Verdana Bold") {
svgText.setAttribute("font-family", "Verdana");
svgText.setAttribute("font-weight", "bold");
}
else if (fontFamily == "Arial Bold") {
svgText.setAttribute("font-family", "Arial");
svgText.setAttribute("font-weight", "bold");
}
else if (fontFamily == "Calibri Bold") {
svgText.setAttribute("font-family", "Calibri");
svgText.setAttribute("font-weight", "bold");
}
else {
svgText.setAttribute("font-family", "" + fontFamily + "");
}
//
svgText.setAttribute("x", "5");
svgText.setAttribute("y", depth);
svgText.setAttribute("id", "bg_txt");
//
debugger;
var textWidth = svgText.getAttribute("textLength");
var x = (width - textWidth)/2;
rectNull.setAttribute("x", x);
rectNull.setAttribute("y", "0");
rectNull.setAttribute("stroke", "null");
rectNull.setAttribute("fill", "none");
rectNull.setAttribute("height", depth);
rectNull.setAttribute("width", width);
//
g2.appendChild(rectNull);
g2.appendChild(svgText);
g.appendChild(g2);
svg.appendChild(g);
}
<div class="table table-bordered" id="btext" style="border:none;">
<div class="bTexts">
<span style="color:#000;font-size:15px; font-family:Helvetica">Text Value:</span><br />
<input type="text" id="bg_svgtext" placeholder="Enter your text value" value="Floor Plan" style="font-size:14px;height:16px; width:220px;margin-top:7px;font-family:Helvetica" />
</div>
<div>
<table style="margin-top:10px;color:#000;font-size:13px; font-weight:bold; font-family:Helvetica;">
<tr>
<td style="padding:0px; padding-right:22px;"><span style="">Width:</span></td>
<td style="padding:0px; padding-right:22px;"><input id="w1" type="text" name="width" value="100" style="width:30px;height:16px;" />m</td>
<td style="padding:0px; padding-right:22px;"><input id="w2" type="text" name="width" value="0" style="width:30px;height:16px;" />cm</td>
</tr>
<tr style="">
<td style="padding:0px; padding-right:22px;padding-top:8px;"><span style="">Depth:</span></td>
<td style="padding:0px; padding-right:22px;padding-top:8px;"><input id="d1" type="text" name="Depth" value="100" style="width:30px;height:16px;" />m</td>
<td style="padding:0px; padding-right:22px;padding-top:8px;"><input id="d2" type="text" name="Depth" value="0" style="width:30px;height:16px;" />cm</td>
</tr>
</table>
</div>
<div class="boothname" style="margin-bottom:10px;padding-left:0px;">
<span style="font-family: Helvetica; font-size:15px;">Font Settings</span>
</div>
<div>
<table style="color:#000;font-size:13px; width:210px; font-weight:bold; font-family:Helvetica;">
<tr>
<td><span style="padding-right:20px;">Font</span></td>
<td style="padding-left:60px;">
<select id="family" style="color:black; width:100px; height:23px; font-size:11px;padding: 2px 26px 2px 10px !important;background-position: calc(114% - 22px) calc(1em + 0px), calc(114% - 17px) calc(1em + 0px), 120% 0;" class="form-control classic ddldesign">
<option style="font-size:12px;" value="Fira">Fira</option>
<option style="font-size:12px;" value="Fira Bold">Fira Bold</option>
<option style="font-size:12px;" value="Verdana">Verdana</option>
<option style="font-size:12px;" value="Verdana Bold">Verdana Bold</option>
<option style="font-size:12px;" value="Calibri">Calibri</option>
<option style="font-size:12px;" value="Calibri Bold">Calibri Bold</option>
<option style="font-size:12px;" value="Arial">Arial</option>
<option style="font-size:12px;" value="Arial Bold">Arial Bold</option>
</select>
</td>
</tr>
<tr>
<td><span>Color</span></td>
<td style="padding-left:60px;"><input type="color" style="width:20px;" name="color" value="#046FAA" id="clr" /></td>
</tr>
<tr>
<td><span>Alpha</span></td>
<td style="padding-left:60px;">
<input type="range" oninput="opacityValue()" min="0" max="100" value="100" style="width:50px;float:left;" id="myRange">
<span id="opacityValue" style="margin-left:5px;">(1)</span>
</td>
</tr>
</table>
</div>
<div class="boothname" style="margin-bottom:10px;padding-left:0px;">
<div style="font-family: Helvetica; font-size:15px;">Click For Add To The Floor</div>
<div style="margin-left:85px; margin-top:5px;"><button class="btn" style="height:26px; padding: 5px 20px" onclick="txtOnFloor()">Add</button></div>
</div>
</div>
<div>
<svg id="svgcontent">
<g></g>
<g></g>
</svg>
</div>
我尝试了添加按钮单击的功能,但字体受到干扰。
如果 getBBox 有效,我该如何实现它?
最佳答案
为了使示例更清晰,我将其缩短为相关部分。最好的策略是让浏览器为您调整文本大小。它适用于所有宽高比,因此不需要区分大小写。
- 首先,添加固定字体大小的文本
将其添加到文档后(以便实际呈现),获取其边界框的大小。对于
.getBBox()
文本元素的方法each glyph must be treated as a separate graphics element. The calculations must assume that all glyphs occupy the full glyph cell. The full glyph cell must have width equal to the horizontal advance and height equal to the EM box for horizontal text.
如果你包围
<text>
具有内部的元素<svg>
元素,您可以定义viewBox
属性等于该边界框。如果宽度和高度属性符合您所需的最终尺寸,文本将自动适合。preserveAspectRatio
属性定义了该拟合的确切规则。
var width = 100, height = 100, text="Floor Plan";
var content = document.querySelector("#svgcontent");
// add a rect to visualize the target size
var rectNull = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rectNull.classList.add("booth-outline");
rectNull.setAttribute("width", width);
rectNull.setAttribute("height", height);
content.appendChild(rectNull);
// inner svg as a container for the text with sizing capabilities
var innerSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
innerSvg.classList.add("booth");
// target sizes
innerSvg.setAttribute("width", width);
innerSvg.setAttribute("height", height);
// position text content to the bottom left such that its size
// fills the target dimensions
innerSvg.setAttribute("preserveAspectRatio", "xMinYMax meet");
// text content
var svgText = document.createElementNS("http://www.w3.org/2000/svg", "text");
svgText.textContent = text;
innerSvg.appendChild(svgText);
// render
content.appendChild(innerSvg);
// and measure size
var box = svgText.getBBox();
// convert to viewBox attribute format
var viewBox = [box.x, box.y, box.width, box.height].join(" ");
innerSvg.setAttribute("viewBox", viewBox);
#svgcontent {
overflow: visible;
}
.booth-outline {
fill: none;
stroke: black;
}
.booth text {
font-family: serif;
font-size: 10px;
}
<svg id="svgcontent" width="250" height="250"></svg>
关于javascript - 如何使用 JavaScript 动态调整 SVG 中文本元素的高度和宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54037851/