javascript - 如何使用 JavaScript 动态调整 SVG 中文本元素的高度和宽度

标签 javascript svg

我正在开发一个项目,我必须使用具有给定文本框架宽度和高度的 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/

相关文章:

javascript - 将数组分成两部分

JavaScript ImageSlider 不起作用

javascript - 资源解释为文档但使用 MIME 类型传输 image/svg+xml :

html - 如何将 SVG 对象插入带有链接的 HTML 中?

jQuery追加用img替换图像

javascript - 将具有重复键的键值数组转换为具有唯一键和值数组属性的对象数组

javascript - three.js CameraHelper 旋转速度比 PerspectiveCamera 快

svg - 来自官方网站的 feComposite 代码示例无法正常工作

c++ - 如何使用 QT 从 SVG 文件中获取值

javascript - 如何计算mongodb中两个集合中一个字段的不同值的数量