Add ellipses to overflowing text in SVG?

前端 未结 6 1053
广开言路
广开言路 2020-11-30 03:20

I\'m using D3.js. I\'d like to find an SVG equivalent to this CSS class, which adds ellipses if text flows out of its containing div:



        
相关标签:
6条回答
  • 2020-11-30 03:41

    If you write CSS it won't work on . Instead of that write logic and append '...' in string.

    0 讨论(0)
  • 2020-11-30 03:43

    I am not aware of an equivalent CSS class for SVG, but you can use foreignObject to embed HTML in SVG. This gives you access to this functionality and is more flexible in general (e.g. you can do automatic line breaking easily).

    See here for a complete example.

    0 讨论(0)
  • 2020-11-30 03:45

    a wrapper function for overflowing text:

        function wrap() {
            var self = d3.select(this),
                textLength = self.node().getComputedTextLength(),
                text = self.text();
            while (textLength > (width - 2 * padding) && text.length > 0) {
                text = text.slice(0, -1);
                self.text(text + '...');
                textLength = self.node().getComputedTextLength();
            }
        } 
    

    usage:

    text.append('tspan').text(function(d) { return d.name; }).each(wrap);
    
    0 讨论(0)
  • 2020-11-30 03:49

    This function does not depend on d3:

    function textEllipsis(el, text, width) {
      if (typeof el.getSubStringLength !== "undefined") {
        el.textContent = text;
        var len = text.length;
        while (el.getSubStringLength(0, len--) > width) {
            el.textContent = text.slice(0, len) + "...";
        }
      } else if (typeof el.getComputedTextLength !== "undefined") {
        while (el.getComputedTextLength() > width) {
          text = text.slice(0,-1);
          el.textContent = text + "...";
        }
      } else {
        // the last fallback
        while (el.getBBox().width > width) {
          text = text.slice(0,-1);
          // we need to update the textContent to update the boundary width
          el.textContent = text + "...";
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-30 03:53
    function trimText(text, threshold) {
        if (text.length <= threshold) return text;
        return text.substr(0, threshold).concat("...");
    }
    

    Use this function to set the SVG node text. The value for the threshold (eg. 20) depends on you. This means that you will display up to 20 characters from your node text. All the texts grater than 20 characters will be trim and display "..." at the end of the trim text.

    Usage eg. :

    var self = this;
    nodeText.text(x => self.trimText(x.name, 20)) // nodeText is the text element of the SVG node
    
    0 讨论(0)
  • 2020-11-30 03:56

    Just an update on the wrap function proposed by user2846569. getComputedTextLength() tends to be really slow, so...

    EDIT

    I diligently applied the advice by user2846569 and made a version with "binary" search, with some calibration and parametrized precision.

    'use strict';
    
    var width = 2560;
    
    d3.select('svg').attr('width', width);
    
    // From http://stackoverflow.com/questions/10726909/random-alpha-numeric-string-in-javascript
    function randomString(length, chars) {
        var result = '';
        for (var i = length; i > 0; --i)
            result += chars[Math.floor(Math.random() * chars.length)];
        return result;
    }
    
    function wrap() {
        var self = d3.select(this),
            textWidth = self.node().getComputedTextLength(),    // Width of text in pixel.
            initialText = self.text(),                          // Initial text.
            textLength = initialText.length,                    // Length of text in characters.
            text = initialText,
            precision = 10, //textWidth / width,                // Adjustable precision.
            maxIterations = 100; // width;                      // Set iterations limit.
    
        while (maxIterations > 0 && text.length > 0 && Math.abs(width - textWidth) > precision) {
    
            text = /*text.slice(0,-1); =*/(textWidth >= width) ? text.slice(0, -textLength * 0.15) : initialText.slice(0, textLength * 1.15);
            self.text(text + '...');
            textWidth = self.node().getComputedTextLength();
            textLength = text.length;
            maxIterations--;
        }
        console.log(width - textWidth);
    }
    
    var g = d3.select('g');
    
    g.append('text').append('tspan').text(function(d) {
        return randomString(width, 'a');
    }).each(wrap);
    

    View on JSFiddle.

    0 讨论(0)
提交回复
热议问题