这个 HTML 文件是一个简单的 SVG 路径的动画效果网页,包含了一个带有 SVG 图形的锚点元素(a),并通过 GSAP 库实现了 SVG 路径的动画效果。
大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。
演示效果

HTML&CSS
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
@import url("https://fonts.googleapis.com/css2?family=Life+Savers:wght@800&display=swap");
html,
body {
height: 100%;
}
body {
background-color: #f6dcfc;
display: flex;
justify-content: center;
align-items: center;
}
a {
height: 100px;
}
path {
stroke: #ed5af2;
stroke-width: 4px;
fill: none;
stroke-linecap: round;
}
text {
fill: #0568f2;
font-family: "Life Savers", serif;
font-weight: 800;
font-style: normal;
font-size: 28px;
}
</style>
</head>
<body>
<a href="#" id="anchor">
<svg viewBox="0 0 200 120" width="200px" height="120px">
<path id="top" d="M 10,70 Q 100,70 190,70" />
<text class="path-text">
<textPath href="#top" startOffset="50%" text-anchor="middle">
<tspan dy="-12">Hover me!</tspan>
</textPath>
</text>
</svg>
</a>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/gsap.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
const anchor = document.getElementById("anchor");
const animateTo = (d, ease, duration = 1) => {
gsap.killTweensOf("#top");
gsap.to("#top", {
attr: { d },
ease,
duration
});
};
anchor.addEventListener("pointerenter", () => {
animateTo("M 10,70 Q 100,20 190,70", "elastic.out(1.4, 0.4)", 0.8);
});
anchor.addEventListener("pointerleave", () => {
animateTo("M 10,70 Q 100,70 190,70", "elastic.out(1.8, 0.2)", 1.5);
});
});
</script>
</body>
</html>
HTML
- a anchor:这是一个锚点元素,通常用于链接。这里通过 id="anchor" 设置了一个唯一标识符,方便在 JavaScript 中引用。
- 内部包含一个 SVG 图形,用于显示一个带有文字的路径。
- svg :定义了一个 SVG 图形,其视图框(viewBox)为 0 0 200 120,表示 SVG 的宽度为 200 像素,高度为 120 像素。
- SVG 内部包含一个路径(path)和一个文本元素(text)。
- path id="top" d="M 10,70 Q 100,70 190,70" :定义了一个 SVG 路径,id="top" 设置了唯一标识符。
- d="M 10,70 Q 100,70 190,70":路径的定义,表示从点 (10, 70) 开始,通过贝塞尔曲线(Q)绘制到点 (190, 70)。
- path-text:定义了一个文本元素,class="path-text" 设置了样式类。
- textPath:将文本沿着 SVG 路径(#top)显示,startOffset="50%" 表示文本从路径的中间开始,text-anchor="middle" 表示文本居中对齐。
- tspan:定义了文本内容 Hover me!,并将其垂直偏移 -12 个单位,使其位置更合适。
CSS
- html, body:height: 100%;:确保 HTML 和 body 的高度占满整个视口。
- body:background-color: #f6dcfc;:设置背景颜色为淡紫色。
- display: flex; justify-content: center; align-items: center;:使用 Flexbox 布局,将内容水平和垂直居中。
- a:height: 100px;:设置锚点元素的高度为 100 像素。
- path:stroke: #ed5af2;:设置路径的描边颜色为紫色。stroke-width: 4px;:设置描边宽度为 4 像素。fill: none;:路径内部不填充颜色。stroke-linecap: round;:描边的端点为圆形。
- text:fill: #0568f2;:设置文本颜色为蓝色。font-family: "Life Savers", serif;:使用导入的字体 Life Savers。font-weight: 800;:字体加粗。font-style: normal;:字体样式为正常。font-size: 28px;:字体大小为 28 像素。
JavaScript 逻辑部分
js
<script>
document.addEventListener("DOMContentLoaded", () => {
const anchor = document.getElementById("anchor");
const animateTo = (d, ease, duration = 1) => {
gsap.killTweensOf("#top");
gsap.to("#top", {
attr: { d },
ease,
duration
});
};
anchor.addEventListener("pointerenter", () => {
animateTo("M 10,70 Q 100,20 190,70", "elastic.out(1.4, 0.4)", 0.8);
});
anchor.addEventListener("pointerleave", () => {
animateTo("M 10,70 Q 100,70 190,70", "elastic.out(1.8, 0.2)", 1.5);
});
});
</script>
1. DOMContentLoaded 事件
- document.addEventListener("DOMContentLoaded", () => { ... });:当文档加载完成时,执行回调函数。
2. animateTo 函数
- const animateTo = (d, ease, duration = 1) => { ... };:定义了一个函数,用于动画效果。
- gsap.killTweensOf("#top");:停止所有针对 SVG 路径 #top 的动画。
- gsap.to("#top", { attr: { d }, ease, duration });:使用 GSAP 库,将路径 #top 的 d 属性(路径定义)动画化到新的值 d,使用指定的缓动函数 ease 和持续时间 duration。
3. pointerenter 和 pointerleave 事件
- anchor.addEventListener("pointerenter", () => { ... });:当鼠标悬停在锚点上时,触发回调函数。
- 调用 animateTo 函数,将路径动画化为一个向上弯曲的曲线(M 10,70 Q 100,20 190,70),使用弹性缓动函数 elastic.out(1.4, 0.4),持续时间为 0.8 秒。
- anchor.addEventListener("pointerleave", () => { ... });:当鼠标离开锚点时,触发回调函数。
- 调用 animateTo 函数,将路径动画化回原始的水平线(M 10,70 Q 100,70 190,70),使用弹性缓动函数 elastic.out(1.8, 0.2),持续时间为 1.5 秒。
各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!