Как динамически изменить высоту и ширину текстового элемента в SVG с помощью JavaScript - PullRequest
0 голосов
/ 04 января 2019

Я работаю над проектом, в котором мне нужно динамически добавлять элемент Svg Text, используя javascript с заданной шириной и высотой текстового фрейма, не нарушая соотношение шрифта. Я не могу этого сделать, пожалуйста, помогите мне.

Заранее спасибо

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 голосов
/ 04 января 2019

Чтобы сделать пример более понятным, я сократил его до соответствующих частей. Лучшая стратегия - позволить браузеру подбирать размер текста для вас. Он будет работать для всех соотношений сторон, поэтому различие в регистре не требуется.

  • сначала добавьте текст с фиксированным размером шрифта
  • после того, как он был добавлен в документ (так, чтобы он действительно отображался), получите размер его ограничительной рамки. Для метода .getBBox() для текстовых элементов

    каждый глиф должен рассматриваться как отдельный графический элемент. Расчеты должны предполагать, что все глифы занимают ячейка полного глифа . Полная ячейка глифа должна иметь ширину, равную горизонтальному продвижению, и высоту, равную блоку EM для горизонтального текста.

  • Если вы окружите элемент <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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...