Основная идея заключается в том, что путь должен свернуть дважды.И когда startOffset
равен 50%, вы делаете его равным 0. Кроме того, поскольку длина пути изменяется при изменении размера окна, вам необходимо пересчитать размер шрифта.Надеюсь, это поможет.
function Init() {
let w = wrap.clientWidth;
let h = wrap.clientHeight;
ellipse.setAttributeNS(null, "viewBox", `0 0 ${w} ${h}`);
let d = `M${w / 10},${h / 2}A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 *
w /
10} ${5 * h / 10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${w / 10} ${5 *
h /
10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 * w / 10} ${5 * h / 10} A${4 *
w /
10},${4 * h / 10} 0 0 0 ${w / 10} ${5 * h / 10}`;
thePath.setAttributeNS(null, "d", d);
let paths_length = thePath.getTotalLength();
tp.style.fontSize = paths_length / 205;
}
window.setTimeout(function() {
Init();
window.addEventListener("resize", Init, false);
}, 15);
let so = 0;
function Marquee() {
requestAnimationFrame(Marquee);
tp.setAttributeNS(null, "startOffset", so + "%");
if (so >= 50) {
so = 0;
}
so += 0.05;
}
Marquee();
#wrap{width:100vw; height:100vh}
svg {
background:#eee;
}
<div id="wrap">
<svg id="ellipse" version="1.1" viewBox="0 0 1000 1000">
<path id="thePath" fill="gold" d="M100,500A400,400 0 0 0 900 500 A400,400 0 0 0 100 500 A400,400 0 0 0 900 500 A400,400 0 0 0 100 500" />
<text stroke="#000000" >
<textPath xlink:href="#thePath" dy="5" id="tp">
Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon •
</textPath>
</text>
</svg>
</div>
ОБНОВЛЕНИЕ
ОП комментирует:
Этот фрагмент кода работает нормально дляслучай использования, но когда я пытаюсь применить его к другому семейству шрифтов, размеры отключаются, и два цикла начинают перекрываться
Одно простое исправление - установить атрибут textLength
равным длинепути, разделенного на 2 (поскольку путь свернут в два раза - это вдвое больше, чем должно быть).Также вам нужно использовать lengthAdjust="spacingAndGlyphs"
, который контролирует, как текст растягивается или сжимается до этой длины.
function Init() {
let w = wrap.clientWidth;
let h = wrap.clientHeight;
ellipse.setAttributeNS(null, "viewBox", `0 0 ${w} ${h}`);
let d = `M${w / 10},${h / 2}A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 *
w /
10} ${5 * h / 10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${w / 10} ${5 *
h /
10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 * w / 10} ${5 * h / 10} A${4 *
w /
10},${4 * h / 10} 0 0 0 ${w / 10} ${5 * h / 10}`;
thePath.setAttributeNS(null, "d", d);
let path_length = thePath.getTotalLength();
//////////////////////////////////////////////////
tp.setAttributeNS(null,"textLength",path_length/2)
//////////////////////////////////////////////////
tp.style.fontSize = path_length / 200;
}
window.setTimeout(function() {
Init();
window.addEventListener("resize", Init, false);
}, 15);
let so = 0;
function Marquee() {
requestAnimationFrame(Marquee);
tp.setAttributeNS(null, "startOffset", so + "%");
if (so >= 50) {
so = 0;
}
so += 0.05;
}
Marquee();
#wrap{width:100vw; height:100vh}
svg {
background:#eee;
font-family:consolas;
}
<div id="wrap">
<svg id="ellipse" version="1.1" viewBox="0 0 1000 1000">
<path id="thePath" fill="gold" d="M100,500A400,400 0 0 0 900 500 A400,400 0 0 0 100 500 A400,400 0 0 0 900 500 A400,400 0 0 0 100 500" />
<text stroke="#000000" >
<textPath xlink:href="#thePath" id="tp" lengthAdjust="spacingAndGlyphs">Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • </textPath>
</text>
</svg>
</div>
Вам также может понадобиться добавить / удалить некоторые Coming Soon •
, если текст становится слишком растянутым / сжатым.
ОБНОВЛЕНИЕ 2
Очевидно, последнее решение не работает в Firefox.Это еще одно решение этой проблемы.
Изначально я устанавливаю размер шрифта намного больше, чем нужно.Затем я проверяю, больше ли длина текста, чем половина длины пути, и если да, то я уменьшаю размер шрифта.Я делаю это во время цикла:
function Init() {
let w = wrap.clientWidth;
let h = wrap.clientHeight;
ellipse.setAttributeNS(null, "viewBox", `0 0 ${w} ${h}`);
let d = `M${w / 10},${h / 2}A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 *
w /
10} ${5 * h / 10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${w / 10} ${5 *
h /
10} A${4 * w / 10},${4 * h / 10} 0 0 0 ${9 * w / 10} ${5 * h / 10} A${4 *
w /
10},${4 * h / 10} 0 0 0 ${w / 10} ${5 * h / 10}`;
thePath.setAttributeNS(null, "d", d);
let path_length = thePath.getTotalLength();
//begin at a bigger size than needed
let font_size = 100;
ellipse.style.fontSize = font_size+"px";
// while the text length is bigger than half path length
while(tp.getComputedTextLength() > path_length / 2 ){
//reduce the font size
font_size -=.25;
//reset the font size
ellipse.style.fontSize = font_size+"px";
}
}
window.setTimeout(function() {
Init();
window.addEventListener("resize", Init, false);
}, 15);
let so = 0;
function Marquee() {
requestAnimationFrame(Marquee);
tp.setAttributeNS(null, "startOffset", so + "%");
if (so >= 50) {
so = 0;
}
so += 0.02;
}
Marquee();
html, body {
margin: 0;
height: 100%;
width: 100%;
}
body {
font-family: "Arimo", sans-serif;
}
#wrap{
width:100%;
height:100%;
position: fixed;
top: 0;
left: 0;
}
text {
text-transform: uppercase;
font-weight: lighter;
}
<div id="wrap">
<svg id="ellipse" version="1.1" viewBox="0 0 1000 1000">
<path id="thePath" fill="transparent" d="M100,500A400,400 0 0 0 900 500 A400,400 0 0 0 100 500" />
<text stroke="black">
<textPath xlink:href="#thePath" dy="5" id="tp" lengthAdjust="spacingAndGlyphs">Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon •</textPath>
</text>
</svg>
</div>