Câu hỏi Cách đặt và căn giữa văn bản trong hình chữ nhật SVG


Tôi có hình chữ nhật sau ...

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

Tôi muốn căn giữa từ "Viễn tưởng" bên trong 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.

Hãy nhìn vào http://www.w3.org/TR/SVG/text.html#TextElement ví dụ không giúp ích vì x và y của phần tử văn bản khác với 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 sẽ không hoạt động.)


76
2018-04-05 02:00


gốc




Các câu trả lời:


SVG 1.2 Gói văn bản nhỏ được thêm vào, nhưng hầu hết các triển khai SVG mà bạn sẽ tìm thấy trong trình duyệt (ngoại trừ Opera) đã không triển khai tính năng này. 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 tả SVG 1.1 cung cấp một cái nhìn tổng quan về giới hạn này, và các giải pháp có thể khắc phục nó:

Mỗi phần tử ‘văn bản’ gây ra một   chuỗi văn bản được hiển thị. 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 gói tác giả cần   để tính toán các ngắt dòng và sử dụng trước   nhiều phần tử ‘văn bản’ (một cho mỗi phần tử   dòng văn bản).
  • Tác giả hoặc tác giả   gói cần tính toán trước dòng   ngắt và sử dụng một phần tử ‘văn bản’   với một hoặc nhiều con 'tspan'   các phần tử có giá trị thích hợp cho   các thuộc tính ‘x’, ‘y’, ‘dx’ và ‘dy’ cho   đặt vị trí bắt đầu mới cho những vị trí đó   ký tự bắt đầu dòng mới.   (Cách tiếp cận này cho phép văn bản người dùng   lựa chọn trên nhiều dòng   văn bản - xem Lựa chọn văn bản và   hoạt động trên khay nhớ tạm.)
  • Thể hiện   văn bản được hiển thị trong một XML khác   không gian tên như XHTML [XHTML]   nội tuyến nhúng trong   Phần tử 'foreignObject'. (Lưu ý:   ngữ nghĩa chính xác của phương pháp này là   không hoàn toàn được xác định tại thời điểm này.)

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

Là một gói nguyên thủy, gói văn bản có thể được mô phỏng bằng cách sử dụng thuộc tính dy và các phần tử tspan, và như đã đề cập trong spec, 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

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

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

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


34
2018-04-05 04:10



Và thậm chí không bắt tôi bắt đầu với những gì liên quan đến việc tạo ra có thể chỉnh sửa bản văn... - jbeard4
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 chỉ tôi mới có thể làm cho trình duyệt hiển thị bảng chính xác.) - Lady Aleena
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, giúp bạn có thể nhận được văn bản có thể chỉnh sửa bằng cách thêm thuộc tính editable="true" thành phần văn bản hoặc phần tử textArea. - Erik Dahlström
@Erik, một lần nữa Opera đang đi trước đường cong. - jbeard4
@ Lena Aleena, tại sao không chỉ sử dụng các giải pháp Inkscape tôi mentinoed? Nếu đó chỉ là hình ảnh tĩnh (ví dụ: không có hành vi động, không có nội dung văn bản cập nhật động), thì điều này sẽ hoạt động tốt. Thêm vào đó, nó sẽ có khả năng mở rộng, mà Paint sẽ không, vì Paint tạo ra đồ họa raster. Cuối cùng, tôi không tin rằng Paint hỗ trợ gói văn bản ở mọi cấp độ. - jbeard4


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

  1. Đặt vị trí của văn bản cho trung tâm tuyệt đối của phần tử mà bạn muốn căn giữa nó:

    • Nếu đó là cha mẹ, bạn chỉ có thể làm x="50%" y ="50%".
    • Nếu đó là một yếu 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 với chiều cao).
  2. Sử dụng text-anchor thuộc tính để căn giữa văn bản theo chiều ngang với giá trị middle:

    ở giữa

    Các ký tự kết xuất được căn chỉnh sao cho trung bình hình học của văn bản được hiển thị kết quả ở vị trí văn bản hiện tại ban đầu.

  3. Sử dụng alignment-baseline thuộc tính để căn giữa 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ó trông như thế nào, bạn có thể muốn làm central)

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

<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>


103
2017-07-20 16:50



Tôi đã tìm kiếm ở khắp mọi nơi cho 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 một con số bên trong thanh tiến trình hướng tâm - anthonytherockjohnson
Trong trường hợp của tôi, đó là dominant-baseline tài sản thực hiện công việc, không phải công việc alignment-baseline. - pintoch
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: stackoverflow.com/a/44857272/3795219 - Austin D
Nếu bạn định thực hiện việc này thường xuyên, bạn cũng có thể thêm các thông tin sau: <style type="text/css"><![CDATA[ text { alignment-baseline: middle; text-anchor:middle; } ]]></style>. Cảm ơn các giải pháp. - Manngo


Các 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 sẽ mong đợi mã sau đây để tạo ra một hình chữ nhật tròn, nhưng các góc được cắt bớt bởi cha mẹ svg thành phần:

<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 text trong một svg và sau đó làm tổ mới svg và rect cùng nhau bên trong một g phần tử, 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 vấn đề clipping xảy ra trong các 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 transform="translate(x,y)" thuộc tính để 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ị rect / text trên màn hình.


7
2017-07-01 04:16





Bạn có thể sử dụng trực tiếp text-anchor = "middle" bất động sản. 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>

4
2017-08-11 21:10



đã chỉnh sửa. Cảm ơn. - Nalin Agrawal


Blog chi tiết đầy đủ: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>


4
2017-11-15 23:50



Không tập trung vào firefox trong khi các giải pháp khác. codepen.io/anon/pen/oEByYr - tgf
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? - Sahil Gupta
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


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

1
2017-11-02 04:02





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

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

var g = d3.select("svg");
					
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>


1
2018-06-20 14:52



Chào mừng bạn đến với Stack Overflow! Xin vui lòng cảm thấy tự do để có một chuyến du lịch của trang web và nếu bạn cần trợ giúp thêm với trang web, hãy kiểm tra điều này ngoài. Ồ, 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, hãy cứ hỏi meta. - Isiah Meadows