2013-04-12 43 views
21

Tôi đang sử dụng D3.js. Tôi muốn tìm một SVG tương đương với lớp CSS này, có thêm elip nếu văn bản chảy ra khỏi div chứa của nó:Thêm dấu ba chấm vào văn bản tràn trong SVG?

.ai-ellipsis { 
    display: block; 
    white-space: nowrap; 
    overflow: hidden; 
    text-overflow: ellipsis; 
    -o-text-overflow: ellipsis; 
    -moz-binding: url(<q>assets/xml/ellipsis.xml#ellipsis</q>); 
} 

Đây là SVG của tôi:

<g class="bar" transform="translate(0,39)"> 
    <text class="label" x="-3" y="6.5" dy=".35em" text-anchor="start">Construction</text>  
    <rect height="13" width="123"></rect> 
</g> 

Nó tạo ra như sau:

barEnter.append("text").attr("class", "label") 
     .attr("x", -3).attr("y", function() { return y.rangeBand()/2}) 
     .attr("dy", ".35em").attr("text-anchor", "start") 
     .text(function(d) { 
      return d.Name; 
     }); 

Hiện tại văn bản đang tràn và chồng chéo phần tử trực tiếp.

Có cách nào tôi có thể nói "nếu văn bản có chiều rộng lớn hơn, cắt và thêm dấu ba chấm" không?

Trả lời

10

Tôi không biết lớp CSS tương đương cho SVG, nhưng bạn có thể sử dụng foreignObject để nhúng HTML vào SVG. Điều này cho phép bạn truy cập vào chức năng này và linh hoạt hơn nói chung (ví dụ: bạn có thể thực hiện ngắt dòng tự động một cách dễ dàng).

Xem here để có ví dụ hoàn chỉnh.

+10

FYI: 'foreignObject' không hoạt động trong bất kỳ phiên bản của IE mặc dù. – WiredPrairie

+1

Xem https://svgwg.org/svg2-draft/text.html#TextOverflowProcessing (Opera/Presto thực hiện việc này, ví dụ tại đây: http: //dahlström.net/svg/css/text-overflow-ellipsis.svg) . –

46

một hàm wrapper cho văn bản tràn:

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(); 
     } 
    } 

sử dụng:

text.append('tspan').text(function(d) { return d.name; }).each(wrap); 
+2

Giải pháp tuyệt vời, lựa chọn nit duy nhất của tôi là chiều rộng và phần đệm không được xác định trong phần biến. – patorjk

+3

@patorjk điều này sẽ được giải quyết bằng cách 'wrap()' trả về một hàm như: 'hàm wrap (width, padding) {return function() {/ * original function * /}}'. Cách sử dụng sẽ là văn bản 'text.append ('tspan'). (Function (d) {return d.name;}) mỗi (wrap (100, 5));' – wvengen

+0

nếu tốc độ được yêu cầu tìm kiếm nhị phân có thể được sử dụng để xác định độ dài văn bản chính xác ... – user2846569

0

Chỉ cần một bản cập nhật về chức năng bọc bởi user2846569 đề xuất. getComputedTextLength() có xu hướng được rất chậm, vì vậy ...

EDIT

Tôi siêng năng áp dụng những lời khuyên bởi user2846569 và tạo ra một phiên bản với tìm kiếm "nhị phân", với một số hiệu chuẩn và độ chính xác tham số.

'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

trên mỗi điểm ảnh bị xóa, bạn xóa một chữ cái, điều này là siêu sai ... – user2846569

+0

Đối với dấu ba chấm, công trình này do điều kiện (chiều dài văn bản> chiều rộng ...). Trong thực tế, cả hai thuật toán sẽ chỉ cắt đủ chữ cái để vừa với vùng chứa. Các chữ cái được cung cấp có kích thước hợp lý (ví dụ: mười pixel trở lên), độ chính xác ở đây đủ để đạt được hiệu suất rất, rất đáng kể. – Argo

+0

Có ví dụ ... văn bản là 'aaaaaaaa' trong đó mỗi chữ cái là 10px ... bỏ qua đệm ... điều này cho chúng ta textLength là 80 px ... cho phép lấy chiều rộng vùng chứa 40px ... chúng tôi sẽ lặp lại 8 lần xóa tất cả 8 chữ cái từ văn bản và kết quả là textLength 72 sẽ vẫn lớn hơn 40 ... – user2846569

2

tôi thực hiện một chức năng có nguồn gốc mà không phụ thuộc vào d3, chức năng này thực hiện 3 fallbacks cách:

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 + "..."; 
    } 
    } 
} 
Các vấn đề liên quan