2011-04-05 59 views
67

Tôi có hình chữ nhật sau ...Làm thế nào để đặt và văn bản trung tâm trong một hình chữ nhật SVG

<rect x="0px" y="0px" width="60px" height="20px"/> 

Tôi muốn tập trung từ "Fiction" bên trong của nó. Đối với các hình chữ nhật khác, không phải là từ bọc của svg để ở trong chúng? Tôi dường như không thể tìm thấy bất cứ điều gì đặc biệt về chèn văn bản trong các hình dạng được căn giữa cả chiều ngang và chiều dọc và từ bọc. Ngoài ra, văn bản không thể rời khỏi hình chữ nhật.

Nhìn vào ví dụ http://www.w3.org/TR/SVG/text.html#TextElement không giúp ích vì chữ x và y của phần tử văn bản khác với chữ x và y của hình chữ nhật. Dường như không có chiều rộng và chiều cao cho các phần tử văn bản. Tôi không chắc chắn về toán học ở đây.

(bảng html của tôi chỉ là sẽ không làm việc.)

Trả lời

32

SVG 1.2 Tiny thêm gói văn bản, nhưng hầu hết các trường của SVG rằng bạn sẽ tìm thấy trong trình duyệt (với ngoại lệ của Opera) đã không thực hiện điều này đặc tính. Nó thường tùy thuộc vào bạn, nhà phát triển, để định vị văn bản theo cách thủ công.

Các SVG 1.1 đặc điểm kỹ thuật cung cấp một cái nhìn tổng quan tốt của hạn chế này, và các giải pháp khả thi để vượt qua nó:

Mỗi phần tử ‘text’ gây ra một chuỗi duy nhất của văn bản để được trả lại. SVG không thực hiện ngắt dòng tự động hoặc gói từ. Để đạt được hiệu quả của nhiều dòng văn bản, sử dụng một trong các phương pháp sau:

  • Tác giả hoặc tác giả gói cần để sẵn tính ngắt dòng và sử dụng nhiều yếu tố 'text' (một cho mỗi dòng dòng văn bản).
  • Tác giả hoặc tác giả gói cần pre-tính toán dòng phá vỡ và sử dụng một 'text' đơn tố với một hoặc nhiều 'tspan' con yếu tố với các giá trị thích hợp cho 'x' thuộc tính, 'y' , 'dx' và 'dy' thành đặt vị trí bắt đầu mới cho những ký tự bắt đầu dòng mới. (Cách tiếp cận này cho phép người sử dụng văn bản lựa chọn trên nhiều dòng văn bản -. Thấy lựa chọn văn bản và hoạt động vào clipboard)
  • Thể hiện các văn bản để được trả lại trong một không gian tên XML như XHTML [XHTML] nhúng inline trong phần tử 'ngoại lệ'. (Lưu ý: ngữ nghĩa chính xác của phương pháp này được không hoàn toàn được xác định vào thời điểm này.)

http://www.w3.org/TR/SVG11/text.html#Introduction

Như một nguyên thủy, văn bản gói có thể được mô phỏng bằng cách sử dụng các thuộc tính dy và các yếu tố tspan và như đã đề cập trong thông số kỹ thuật, một số công cụ có thể tự động hóa điều này. Ví dụ, trong Inkscape, chọn hình dạng bạn muốn, và văn bản bạn muốn, và sử dụng Text -> Flow into Frame. Điều này sẽ cho phép bạn viết văn bản của bạn, với gói, mà sẽ bọc dựa trên các giới hạn của hình dạng. Ngoài ra, hãy đảm bảo bạn làm theo các hướng dẫn này để cho Inkscape biết khả năng tương thích với SVG 1.1: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

Bên cạnh đó, có một số thư viện JavaScript có thể được sử dụng để tự động tự động gói văn bản: http://www.carto.net/papers/svg/textFlow/

Thật thú vị cần lưu ý giải pháp CSVG để gói một hình dạng một yếu tố văn bản (ví dụ như nhìn thấy họ " nút" chẳng hạn), mặc dù nó quan trọng là phải đề cập đến rằng việc thực hiện của họ là không có thể sử dụng trong một trình duyệt: http://www.csse.monash.edu.au/~clm/csvg/about.html

tôi nhắc đến điều này bởi vì tôi đã phát triển một thư viện CSVG lấy cảm hứng từ đó cho phép y để làm những việc tương tự và hoạt động trong trình duyệt web, mặc dù tôi chưa phát hành.

+4

Và thậm chí không làm cho tôi bắt đầu về những gì đang tham gia vào việc tạo ra * có thể chỉnh sửa văn bản ... * – jbeard4

+0

Cảm ơn bạn đã trả lời ... nhưng ACK! Có vẻ như tôi sẽ phải bỏ svg rồi. Một trong những điều đầu tiên các nhà phát triển nên nghĩ đến là đính kèm văn bản (được định dạng như mong muốn của người dùng) thành hình dạng! Tôi sẽ chờ đợi cho đến khi họ có được hành động của họ với nhau trước khi tôi làm nữa với nó. Tôi sẽ cố gắng vẽ lại nó trong Windows Paint và xem liệu nó có làm được không. (Nếu tôi chỉ có thể làm cho trình duyệt hiển thị bảng chính xác.) –

+0

Giới thiệu về văn bản có thể chỉnh sửa trong svg, Opera hỗ trợ thuộc tính có thể chỉnh sửa từ SVG 1.2 Tiny, cho phép có thể chỉnh sửa văn bản bằng cách thêm thuộc tính 'editable =" true "' đến phần tử văn bản hoặc phần tử textArea. –

1

Tôi đã có một bugger của một thời gian nhận được bất cứ điều gì tập trung bằng cách sử dụng SVG, vì vậy tôi cuộn chức năng nhỏ của riêng tôi. hy vọng nó sẽ giúp bạn. Lưu ý rằng nó chỉ hoạt động cho các phần tử SVG.

function centerinparent(element) { //only works for SVG elements 
    var bbox = element.getBBox(); 
    var parentwidth = element.parentNode.width.baseVal.value; 
    var parentheight = element.parentNode.height.baseVal.value; 
    var newwidth = ((parentwidth/2) - (bbox.width/2)) - 2; //i start everything off by 2 to account for line thickness 
    var newheight = ((parentheight/2) - (bbox.height/2)) - 2; 
    //need to adjust for line thickness?? 

    if (element.classList.contains("textclass")) { //text is origined from bottom left, whereas everything else origin is top left 
     newheight += bbox.height; //move it down by its height 
    } 

    element.setAttributeNS(null, "transform", "translate(" + newwidth + "," + newheight + ")"); 
    // console.log("centering BOXES: between width:"+element.parentNode.width.baseVal.value + " height:"+parentheight); 
    // console.log(bbox); 
} 
83

Một giải pháp dễ dàng để tập trung văn bản theo chiều ngang và theo chiều dọc trong SVG:

  1. Đặt vị trí của văn bản vào trung tâm tuyệt đối của nguyên tố này mà bạn muốn căn giữa:

    • Nếu đó là cha mẹ, bạn chỉ có thể thực hiện x="50%" y ="50%".
    • Nếu đó là một phần tử khác, x sẽ là x của phần tử đó + một nửa chiều rộng của nó (và tương tự cho y nhưng có chiều cao).
  2. Sử dụng text-anchor tài sản để tập trung các văn bản theo chiều ngang với giá trị middle:

    giữa

    Các nhân vật trả lại được liên kết như vậy mà giữa hình học của văn bản trả lại kết quả là tại vị trí văn bản hiện tại ban đầu.

  3. Sử dụng alignment-baseline tài sản để tập trung các văn bản theo chiều dọc với giá trị middle (hoặc tùy thuộc vào cách bạn muốn nó như thế nào, bạn có thể muốn làm central)

Đây là một đơn giản demo:

<svg width="200" height="100"> 
 
    <rect x="0" y="0" width="200" height="100" stroke="red" stroke-width="3px" fill="white"/> 
 
    <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">TEXT</text>  
 
</svg>

+0

Tôi đã tìm kiếm ở khắp mọi nơi một giải pháp đơn giản này - không có gì khác đang làm việc cho tôi. Tôi sử dụng điều này để định tâm số bên trong thanh tiến trình hướng tâm – anthonytherockjohnson

+3

Trong trường hợp của tôi, đó là thuộc tính 'chi phối cơ sở 'thực hiện công việc, chứ không phải 'căn chỉnh-đường cơ sở'. – pintoch

+0

Thật không may, giải pháp này clip đột quỵ hình chữ nhật. Xem ví dụ của tôi bên dưới để biết giải pháp tránh cắt bớt: https://stackoverflow.com/a/44857272/3795219 –

4

Bạn có thể trực tiếp sử dụng thuộc tính text-anchor = "middle". Tôi khuyên bạn nên tạo một phần tử bao bọc svg trên hình chữ nhật và văn bản của bạn. Bằng cách đó bạn có thể sử dụng toàn bộ phần tử bằng cách sử dụng một bộ chọn css. Đảm bảo bạn đặt thuộc tính 'x' và 'y' của văn bản là 50%.

<svg class="svg-rect" width="50" height="40"> 
     <rect x="0" y="0" rx="3" ry="3" width="50" height="40" fill="#e7e7e7"></rect> 
     <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="1px" dy=".3em">N/A</text> 
    </svg> 
+0

. Cảm ơn. –

0

Một cách để chèn văn bản bên trong hình chữ nhật là chèn một đối tượng nước ngoài, đó là DIV, bên trong đối tượng trực tiếp.

Bằng cách này, văn bản sẽ tuân thủ các giới hạn của DIV.

var g = d3.select("svg"); 
 
\t \t \t \t \t 
 
g.append("rect") 
 
.attr("x", 0) 
 
.attr("y", 0) 
 
.attr("width","100%") 
 
.attr("height","100%") 
 
.attr("fill","#000"); 
 

 

 
var fo = g.append("foreignObject") 
 
.attr("width","100%"); 
 

 
fo.append("xhtml:div") 
 
    .attr("style","width:80%;color:#FFF;margin-right: auto;margin-left: auto;margin-top:40px") 
 
    .text("Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.js"></script> 
 
<svg width="200" height="200"></svg>

+0

Chào mừng bạn đến với Stack Overflow! Vui lòng tham gia [tour] (// stackoverflow.com/tour) của trang web và nếu bạn cần trợ giúp thêm với trang web, hãy xem [this] (// stackoverflow.com/help). Ồ, và nếu bạn từng gặp phải các vấn đề mà trang trợ giúp không bao gồm, vui lòng hỏi [meta] (// meta.stackoverflow.com/). –

5

Những câu trả lời trước đó đã cho kết quả kém khi sử dụng các góc tròn hoặc stroke-width đó là> 1. Ví dụ, bạn mong chờ đoạn mã sau để tạo ra một hình chữ nhật tròn, nhưng các góc được cắt bớt các thành phần cha mẹ svg:

<svg width="200" height="100"> 
 
    <!--this rect should have rounded corners--> 
 
    <rect x="0" y="0" rx="5" ry="5" width="200" height="100" stroke="red" stroke-width="10px" fill="white"/> 
 
    <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CLIPPED BORDER</text>  
 
</svg>

Thay vào đó, tôi khuyên bạn nên gói các text trong một svg và sau đó lồng nhau mới svgrect với nhau bên trong một phần tử g, như trong ví dụ sau:

<!--the outer svg here--> 
 
<svg width="400px" height="300px"> 
 

 
    <!--the rect/text group--> 
 
    <g transform="translate(50,50)"> 
 
    <rect rx="5" ry="5" width="200" height="100" stroke="green" fill="none" stroke-width="10"/> 
 
    <svg width="200px" height="100px"> 
 
     <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CORRECT BORDER</text>  
 
    </svg> 
 
    </g> 
 

 
    <!--rest of the image's code--> 
 
</svg>

Điều này khắc phục sự cố cắt xảy ra trong câu trả lời ở trên. Tôi cũng đã dịch nhóm trực tràng/văn bản bằng cách sử dụng thuộc tính transform="translate(x,y)" để chứng minh rằng điều này cung cấp một cách tiếp cận trực quan hơn để định vị trực tiếp/văn bản trên màn hình.

2

Full Detail Blog: http://blog.techhysahil.com/svg/how-to-center-text-in-svg-shapes/

<svg width="600" height="600"> 
 
    <!-- Circle --> 
 
    <g transform="translate(50,40)"> 
 
    <circle cx="0" cy="0" r="35" stroke="#aaa" stroke-width="2" fill="#fff"></circle> 
 
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text> 
 
    </g> 
 
    
 
    <!-- In Rectangle text position needs to be given half of width and height of rectangle respectively --> 
 
    <!-- Rectangle --> 
 
    <g transform="translate(150,20)"> 
 
    <rect width="150" height="40" stroke="#aaa" stroke-width="2" fill="#fff"></rect> 
 
    <text x="75" y="20" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text> 
 
    </g> 
 
    
 
    <!-- Rectangle --> 
 
    <g transform="translate(120,140)"> 
 
    <ellipse cx="0" cy="0" rx="100" ry="50" stroke="#aaa" stroke-width="2" fill="#fff"></ellipse> 
 
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text> 
 
    </g> 
 
    
 
    
 
</svg>

+0

Không tập trung vào firefox trong khi các giải pháp khác. https://codepen.io/anon/pen/oEByYr – tgf

+0

Tôi đã thử nghiệm trên Firefox 58.0.1 (64 bit), nó hoạt động. Bạn có thể đề cập đến phiên bản mà nó không làm việc cho bạn? –

+0

Firefox 58.0.2 64bit. Các văn bản là hơi cao hơn nó nên được. Nó có thể không dễ dàng nhận thấy lúc đầu, nhưng nếu hộp của bạn phù hợp rất chặt chẽ thì rõ ràng hơn; hãy thử giảm chiều cao. – tgf

Các vấn đề liên quan