bru*_*uno 6 html javascript css svg
我有一个环绕 SVG 圆圈的文本,该圆圈根据窗口大小进行缩放 - 感谢用户 enxaneta /sf/answers/3922537181/。我想为文本设置动画,使其像选取框一样围绕中心旋转。为此,我的代码目前如下所示:
function Init(){
let wrap = document.getElementById('wrap');
let thePath = document.getElementById('thePath');
let ellipse = document.getElementById('ellipse');
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}`
thePath.setAttributeNS(null,"d", d)
}
window.setTimeout(function() {
Init();
window.addEventListener('resize', Init, false);
}, 15);
let so = 0
function Marquee(){
let tp = document.getElementById('tp');
requestAnimationFrame(Marquee)
tp.setAttributeNS(null,"startOffset",so+"%");
if(so >= 50){so = 0;}
so+= .05
}
Marquee()Run Code Online (Sandbox Code Playgroud)
<div id="wrap">
<svg id="ellipse" version="1.1" viewBox="0 0 1000 1000" preserveAspectRatio="none">
<path id="thePath" fill="transparent" d="M100,500A400,400 0 0 0 900 500 A400,400 0 0 0 100 500" />
<text stroke="black" font-size="20">
<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 • Coming Soon • Coming Soon • Coming Soon • Coming Soon • Coming Soon •
</textPath>
</text>
</svg>
</div>Run Code Online (Sandbox Code Playgroud)
这运行良好,除了文本在曲线末端被“吞下”(见附图)。我想让它在没有任何中断的情况下进行完整的旋转。我曾尝试将so变量更改为负值,但这最终导致文本偏移太远,因此它只会慢慢爬到页面上。我想在一段时间后添加一个文本片段,但这不会考虑到startOffset移动并且可能不起作用......
感谢任何提示,也感谢那些使用 JS 库或插件的人!
主要思想是路径必须盘绕两次。当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();Run Code Online (Sandbox Code Playgroud)
#wrap{width:100vw; height:100vh}
svg {
background:#eee;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
OP 正在评论:
这个片段似乎适用于用例,但是当我尝试将它应用于另一个字体系列时,尺寸关闭并且两个循环开始重叠
一个简单的解决方法是将属性设置为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();Run Code Online (Sandbox Code Playgroud)
#wrap{width:100vw; height:100vh}
svg {
background:#eee;
font-family:consolas;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
Coming Soon •如果文本变得过于拉伸/压扁,您可能还需要添加/删除一些内容。
显然,最后一个解决方案不适用于 Firefox。这是该问题的另一种解决方案。
最初,我将字体大小设置得比需要的大得多。接下来我检查文本长度是否大于路径长度的一半,如果是,我将减小字体大小。我在一个while循环中这样做:
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();Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)