【问题标题】:How to change the height and width of svg <text>,if it is greater than the height and width of svg <rect> in javascript?如何改变svg <text>的高度和宽度,如果它大于javascript中svg <rect>的高度和宽度?
【发布时间】:2018-11-11 07:45:21
【问题描述】:
    <g id="newGroup" >
        <rect class="newClass" id="svg_106"  x="133.2" y="384.5" width="76.2" height="38.1" />
        <text class="newText" id="svg_110" style="pointer-events: inherit;" transform="matrix(0.7912 0 0 1 111.325 414.395)" x="31.5976" y="-12">This is a very long text text text text text</text>
    </g>

我想调整矩形内的文本。某些文本的宽度大于矩形本身的宽度。我想调整文本以使其适合矩形内。

【问题讨论】:

    标签: javascript svg


    【解决方案1】:

    &lt;text&gt; 元素上的 transform 使事情变得有些复杂。

    我要做的是删除转换,然后测量文本的大小。然后你可以给它一个新的变换,适当地缩放它并将它定位在正确的位置。

    adjustText("svg_106", "svg_110");
    
    
    function adjustText(rectId, textId)
    {
      var rectElem = document.getElementById(rectId);
      var textElem = document.getElementById(textId);
      // Get the rectangle bounds
      var rectBBox = rectElem.getBBox();
      // Clear the text position and transform so we can measure the text bounds properly
      textElem.setAttribute("x", "0");
      textElem.setAttribute("y", "0");
      textElem.removeAttribute("transform");
      var textBBox = textElem.getBBox();
      // Calculate an adjusted position and scale for the text
      var padding = 5;  // How much horizontal padding between the text and the rectangle sides
      var scale = (rectBBox.width - 2 * padding) / textBBox.width;
      var textX = rectBBox.x + padding;
      var textY = rectBBox.y + (rectBBox.height / 2) - scale * (textBBox.y + textBBox.height / 2);
      // Add a new transform attribute to the text to position it in the new place with the new scale
      textElem.setAttribute("transform", "translate("+textX+","+textY+") scale("+scale+")");
    }
    .newClass {
      fill: grey;
    }
    <svg viewBox="0 300 500 200">
      <g id="newGroup" >
        <rect class="newClass" id="svg_106"  x="133.2" y="384.5" width="76.2" height="38.1" />
        <text class="newText" id="svg_110" style="pointer-events: inherit;" transform="matrix(0.7912 0 0 1 111.325 414.395)" x="31.5976" y="-12">This is a very long text text text text text</text>
      </g>
    </svg>

    【讨论】:

    • 只要您的 SVG 看起来像您发布的示例,这应该可以工作。如果情况与此有所不同,则可能无法正常工作。例如,如果&lt;rect&gt;transform,则需要修改此代码。
    • 文本的字体太小了。有没有办法让字体大小保持不变,我们可以添加一个断线并在下一行显示剩余的文本
    • SVG 本身不支持多行文本。您需要将文本分成单独的 &lt;text&gt;&lt;tspan&gt; 元素。您需要使用一些 javascript 代码来执行此操作。例如see this question 或库like this one
    【解决方案2】:

    您不需要 javascript。我将文本放在&lt;symbol&gt; 中,并使符号适应矩形的大小。但是,您可以使用 javascript 计算 &lt;symbol&gt; 元素的 viewBox。

    svg{border:1px solid}
    .newClass{stroke:black; fill:none;}
    text{fill:black;}
    <svg viewBox="130 380 100 50">
    
      
    <symbol id="test" viewBox="0 0 260 19">
      <g id="g">
            <text class="newText" id="svg_110"   dominant-baseline="hanging" >This is a very long text text text text text</text>
      </g>
      </symbol> 
    <g id="newGroup" >
            <rect class="newClass" id="svg_106"  x="133.2" y="384.5" width="76.2" height="38.1" />
            <use xlink:href="#test" style="pointer-events: inherit;"  x="133.2" y="384.5" width="76.2" height="38.1"  />
        </g>
      </svg>

    在此示例中,我将展示如何使用 javascript 计算 &lt;symbol&gt; viewBox 属性的值。

    let bbText = svg_110.getBBox();
    test.setAttributeNS(null, "viewBox", `${bbText.x}  ${bbText.y}  ${bbText.width}  ${bbText.height}`)
    svg{border:1px solid}
    .newClass{stroke:black; fill:none;}
    text{fill:black;}
    <svg viewBox="130 380 100 50">
    
    <symbol id="test">
    
            <text class="newText" id="svg_110" dominant-baseline="hanging" > This is a very long text text text text text </text>
    
      </symbol> 
    <g id="newGroup" >
            <rect class="newClass" id="svg_106"  x="133.2" y="384.5" width="76.2" height="38.1" />
            <use xlink:href="#test" style="pointer-events: inherit;"  x="133.2" y="384.5" width="76.2" height="38.1"  />
        </g>
      </svg>

    更新

    OP 评论说她/他无法更改 SVG,但可以动态添加元素。在下一个示例中,我将动态创建 &lt;symbol&gt;&lt;use&gt; 元素。请重新输入我的代码中的 cmets。

    const SVG_NS = 'http://www.w3.org/2000/svg';
    const SVG_XLINK = "http://www.w3.org/1999/xlink";
    let theText = document.querySelector("#svg_110");
    let theRect = document.querySelector("#svg_106");
    
    
    // create a new symbol element
    let symbol = document.createElementNS(SVG_NS, 'symbol');
    symbol.setAttributeNS(null, "id", "theSymbol");
    newGroup.appendChild(symbol);
    
    // get the size of the bounding box for the text
    let bbText = theText.getBBox();
    // set the attribute viewBox for the symbol
    symbol.setAttributeNS(null, "viewBox", `${bbText.x}  ${bbText.y}  ${bbText.width}  ${bbText.height}`)
    
    // clone the text and append it to the symbol
    let txt=theText.cloneNode(true);
    symbol.appendChild(txt);
    
    // remove the text 
    theText.parentNode.removeChild(theText);
    
    
    // create a use element
    let use = document.createElementNS(SVG_NS, 'use');
    // the use element is using the symbol
    use.setAttributeNS(SVG_XLINK, 'xlink:href', '#theSymbol');
    // also is using the rect's attributes 
    use.setAttributeNS(null, 'x', theRect.getAttribute("x"));
    use.setAttributeNS(null, 'y', theRect.getAttribute("y"));
    use.setAttributeNS(null, 'width', theRect.getAttribute("width"));
    use.setAttributeNS(null, 'height', theRect.getAttribute("height"));
    
    
    newGroup.appendChild(use);
    svg{border:1px solid}
    .newClass{stroke:black; fill:none;}
    text{fill:black;}
    <svg viewBox="130 380 150 100">
       <g id="newGroup" >
            <rect class="newClass" id="svg_106"  x="133.2" y="384.5" width="76.2" height="38.1" />
            <text class="newText" id="svg_110" style="pointer-events: inherit;" x="31.5976" y="-12">This is a very long text text text text text</text>
        </g>
    </svg>

    【讨论】:

    • 我的 SVG 很大,它是上面的默认格式,我不能添加 我所能做的就是调整文本大小或如果文本较长则动态添加
    • @Shahid 我用一个额外的例子更新了我的答案,我使用 JS 创建 symboluse 元素。请看一下
    【解决方案3】:

    只需在 JavaScript 中执行此操作:

    var rect = document.getElementById("svg_106");
    var text = document.getElementById("svg_110");
    var aRect = rect.getBoundingClientRect();
    var bRect = text.getBoundingClientRect();
    
    if (aRect.top + aRect.height) < (bRect.top)) ||
        (aRect.top > (bRect.top + bRect.height)) ||
        ((aRect.left + aRect.width) < bRect.left) ||
        (aRect.left > (bRect.left + bRect.width) {
            //Do stuff
    }
    

    【讨论】:

    • getBoundingClientRect() 每次滚动位置改变时都会改变它们的值。所以我会得到完美的值
    猜你喜欢
    • 2018-02-26
    • 2015-03-18
    • 2016-06-15
    • 2017-12-26
    • 2022-01-15
    • 2014-12-11
    • 1970-01-01
    • 2013-11-26
    • 2015-07-09
    相关资源
    最近更新 更多