Как разместить и центрировать текст в прямоугольнике SVG
У меня есть следующий прямоугольник...
<rect x="0px" y="0px" width="60px" height="20px"/>
Я хотел бы сосредоточить слово "фантастика" внутри него. Для других прямоугольников, переносит ли svg слово, чтобы остаться в них? Я не могу найти ничего конкретного о вставке текста в фигуры, которые центрированы как по горизонтали, так и по вертикали и перенос слов. Кроме того, текст не может покинуть прямоугольник.
глядя на http://www.w3.org/TR/SVG/text.html#TextElement пример не помогает поскольку текстовый элемент x и y отличается от прямоугольника x и y. для текстовых элементов, похоже, нет ширины и высоты. Я не уверен в математике здесь.
(моя таблица html просто не будет работать.)
7 ответов:
SVG 1.2 Tiny добавлена текстовая обертка, но большинство реализаций SVG, которые вы найдете в браузере (за исключением Opera), не реализовали эту функцию. Это, как правило, до вас, разработчик, чтобы позиционировать текст вручную.
спецификация SVG 1.1 дает хороший обзор этого ограничения и возможных решений для его преодоления:
каждый элемент "текст" вызывает один строки текста, которые должны быть оказаны. формат SVG выполняет автоматический перенос строк или перенос слов. Для достижения эффекта из нескольких строк текста используйте одну следующие методы:
- автор или авторский пакет должен чтобы предварительно вычислить разрывы строк и использовать несколько текстовых элементов (по одному для каждого строка текста.)
- автор или авторская пакет должен предварительно вычислить строку разрывы и использование одного элемента "текст" с одним или несколькими детьми ‘tspan’ элементы с соответствующими значениями для атрибуты ‘x’, ‘y’, ‘dx’ и ‘dy’ к установлены новые стартовые позиции для тех символы, которые начинают новые строки. (Этот подход позволяет пользователю текст выбор через несколько строк текст -- см. раздел выделение текста и операции с буфером обмена.)
- выразить текст, который будет отображаться в другом XML пространство имен, например XHTML [XHTML] встроенными в элемент 'foreignObject'. (Примечание: точной семантикой этого подхода являются на данный момент полностью не определен.)
http://www.w3.org/TR/SVG11/text.html#Introduction
Как примитив, перенос текста может быть смоделирован с помощью атрибутов dy и элементов tspan, и, как указано в спецификации, некоторые инструменты могут автоматизировать это. Например, в Inkscape, выберите форму вы хотите, и текст, который вы хотите, и использовать текст -> поток в рамке. Это позволит вам написать свой текст, с оберткой, которая будет обертывать на основе границ фигуры. Также убедиться следуйте этим инструкциям, чтобы Inkscape поддерживал совместимость с SVG 1.1: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F
кроме того, существуют некоторые библиотеки JavaScript, которые можно использовать для динамической автоматизации обертывания текста: http://www.carto.net/papers/svg/textFlow/
интересно отметить решение CSVG для обертывания фигуры в текстовый элемент (например, см. Их пример "кнопки"), хотя важно отметить, что их реализация не использовать в браузере: http://www.csse.monash.edu.au / ~clm/csvg/about.html
я упоминаю об этом, потому что я разработал csvg-вдохновленную библиотеку, которая позволяет вам делать подобные вещи и работает в веб-браузерах, хотя я еще не выпустил ее.
простое решение для центрирования текста по горизонтали и вертикали в SVG:
установите положение текста в абсолютный центр элемента, в котором вы хотите центр это:
- если это родитель, вы могли бы просто сделать
x="50%" y ="50%".- если это другой элемент,
xбудетxэтого элемента + половина его ширины (и аналогично дляyно с высота.)использовать
text-anchorсвойство центрировать текст по горизонтали со значениемmiddle:средний
отрисованные символы выровнены таким образом, что геометрическая середина полученного отрисованного текста находится в начальной текущей позиции текста.
использовать
alignment-baselineсвойство центрировать текст по вертикали со значениемmiddle(или в зависимости от того, как вы хотите выглядеть, вы можете сделатьcentral)вот простой пример:
<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>
предыдущие ответы дали плохие результаты при использовании закругленных углов или
stroke-widthэто >1 . Например, вы ожидаете, что следующий код создаст скругленный прямоугольник, но углы обрезаются родительским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>вместо этого, я рекомендую оборачивать
textнаsvgа потом вложить этот новыйsvgиrectвместе внутриgэлемент, как в следующем пример:<!--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>это устраняет проблему отсечения, которая возникает в ответах выше. Я также перевел группу rect / text с помощью
transform="translate(x,y)"атрибут, чтобы продемонстрировать, что это обеспечивает более интуитивный подход к позиционированию прямой/текст на экране.
Вы можете напрямую использовать
text-anchor = "middle"собственность. Я советую создать элемент обертки svg над вашим прямоугольником и текстом. Таким образом, вы можете использовать весь элемент с помощью одного CSS-селектор. Убедитесь, что вы разместили свойство " x " и " y " текста как 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>
полная информация блог: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>
таким образом, текст будет соответствовать пределам 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>
У меня было время, когда я получал что-то центрированное с помощью SVG, поэтому я свернул свою собственную маленькую функцию. надеюсь, это должно помочь вам. Обратите внимание, что он работает только для элементов 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); }
Comments