Как сделать, чтобы текст при использовании textPath был всегда сверху?
Изучаю команду SVG: textPath, которая позволяет разместить текст вдоль криволинейной траектории.
Вот пример из теоретического источника: MDN
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<!-- to hide the path, it is usually wrapped in a <defs> element -->
<!-- <defs> -->
<path id="MyPath" fill="none" stroke="red"
d="M10,90 Q90,90 90,45 Q90,10 50,10 Q10,10 10,40 Q10,70 45,70 Q70,70 75,50" />
<!-- </defs> -->
<text>
<textPath href="#MyPath">
Quick brown fox jumps over the lazy dog.
</textPath>
</text>
</svg>
Приведено много используемых атрибутов, но не хватает основного, как в animateMotion
rotate ="auto"
Как добиться нормального положения текста (не вниз головой ) на всех участках траектории?
Ответы (2 шт):
Рассмотрим на примере, когда траектория представляет собой окружность.
Начало текста всегда совпадает с началом path, то есть с первой M в <path d="M50 200"
Чтобы нижнюю часть траектории заполнить буквами в нормальном расположении, нужно сделать её отдельно от верхней части.
Верхняя половина окружности:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" >
<path id="top" d="M50 200 A150 150 0 0 1 350 200" fill="none" stroke="blue" stroke-width="2" />
</svg>
Добавляем нижнюю половину окружности:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" >
<path id="top" d="M50 200 A150 150 0 1 1 350 200" fill="none" stroke="blue" stroke-width="2" />
<path id="bottom" d="M50 200 A150 150 0 1 0 350 200" fill="none" stroke="crimson" stroke-width="2" />
</svg>
Обратите внимание, что формулы для обоих половинок окружностей практически одинаковы, за исключением флага sweep-flag, который отвечает за направление рисования по часовой -1
или против часовой - 0 ), подробнее здесь
Теперь на верхнюю и нижнюю дугу с помощью textPath размещаем текст.
Ещё один нюанс, раз половинки текста стали самостоятельными, то для них можно выбрать разные атрибуты шрифтов. Например: font-size="36px" font-family="Comic Sans MS" font-weight="bold" fill="grey"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" style="border:0px solid;" >
<path id="top" d="M50 200 A150 150 0 1 1 350 200" fill="none" stroke="#111111" stroke-width="2" />
<path id="bottom" d="M50 200 A150 150 0 1 0 350 200" fill="none" stroke="crimson" stroke-width="2" />
<circle cx="200" cy="200" r="198" fill="none" stroke="grey" stroke-width="4" />
<text dy="-12px" dx="0" font-size="36px" font-family="Times New Roman" font-weight="bold" fill="black" letter-spacing="6" >
<textPath xlink:href="#top" startOffset="5%"> Top arc outside text
</textPath>
</text>
<text dy="32px" dx="0" font-size="36px" font-family="Comic Sans MS" font-weight="bold" fill="grey" letter-spacing="5" >
<textPath xlink:href="#bottom" startOffset="3%"> Bottom arc text outside
</textPath>
</text>
</svg>
Примеры анимации текста
В этих примерах анимации основаны на изменении startOffset, отступ текста от начала направляющей траектории (path)
<textPath xlink:href="#top" startOffset="98%"> Top arc outside text
<animate id="an" attributeName="startOffset" begin="svg1.click" dur="2s" values="98%;3%" fill="freeze" />
</textPath>
#1. Одновременная анимация обоих половинок текста
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" style="border:0px solid;" >
<path id="top" d="M50 200 A150 150 0 1 1 350 200" fill="none" stroke="#111111" stroke-width="2" />
<path id="bottom" d="M50 200 A150 150 0 1 0 350 200" fill="none" stroke="#111111" stroke-width="2" />
<circle cx="200" cy="200" r="198" fill="none" stroke="grey" stroke-width="4" />
<text dy="-12px" dx="0" font-size="36px" font-family="Times New Roman" font-weight="bold" fill="black" letter-spacing="6" >
<textPath xlink:href="#top" startOffset="98%"> Top arc outside text
<animate id="an" attributeName="startOffset" begin="svg1.click" dur="2s" values="98%;3%" fill="freeze" />
</textPath>
</text>
<text dy="32px" dx="0" font-size="36px" font-family="Comic Sans MS" font-weight="bold" fill="grey" letter-spacing="5" >
<textPath xlink:href="#bottom" startOffset="98%"> Bottom arc text outside
<animate attributeName="startOffset" begin="svg1.click" dur="2s" values="98%;3%" fill="freeze" />
</textPath>
</text>
<text y="200" x="100" font-size="42px" font-family="Comic Sans MS" font-weight="bold" fill="grey" letter-spacing="5" >Click me </text>
</svg>
#2. Поочередная анимация половинок текста
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" style="border:0px solid;" >
<path id="top" d="M50 200 A150 150 0 1 1 350 200" fill="none" stroke="#111111" stroke-width="2" />
<path id="bottom" d="M50 200 A150 150 0 1 0 350 200" fill="none" stroke="#111111" stroke-width="2" />
<circle cx="200" cy="200" r="198" fill="none" stroke="grey" stroke-width="4" />
<text dy="-12px" dx="0" font-size="36px" font-family="Times New Roman" font-weight="bold" fill="black" letter-spacing="6" >
<textPath xlink:href="#top" startOffset="98%"> Top arc outside text
<animate id="an" attributeName="startOffset" begin="svg1.click;an2.end+1s" dur="2s" values="98%;3%" fill="freeze" />
</textPath>
</text>
<text dy="32px" dx="0" font-size="36px" font-family="Comic Sans MS" font-weight="bold" fill="grey" letter-spacing="5" >
<textPath xlink:href="#bottom" startOffset="98%"> Bottom arc text outside
<animate id="an2" attributeName="startOffset" begin="an.end" dur="2s" values="98%;3%" fill="freeze" />
</textPath>
</text>
<text y="200" x="100" font-size="42px" font-family="Comic Sans MS" font-weight="bold" fill="grey" letter-spacing="5" >Click me </text>
</svg>
