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

时间:2019-01-04 11:11:04

标签: 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?

1 个答案:

答案 0 :(得分:1)

为使示例更清楚,我将其简化为相关部分。最好的策略是让浏览器为您确定文本的大小。它适用于所有纵横比,因此不需要您区分大小写。

  • 首先,添加固定字体大小的文本
  • ,在将其添加到文档中(以便实际渲染)之后,获取其边框的大小。对于文本元素的.getBBox()方法

      

    每个字形必须被视为单独的图形元素。计算必须假定所有字形都占据full glyph cell。对于水平文本,整个字形单元格的宽度必须等于水平行进,高度必须等于EM框。

  • 如果用内部<text>元素包围<svg>元素,则可以将viewBox属性定义为等于该边界框。如果width和height属性与所需的最终大小匹配,则文本将自动适合。 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>