【问题标题】:Line button animation线条按钮动画
【发布时间】:2019-09-12 03:59:10
【问题描述】:
我需要在按钮上悬停时制作动画线,
从顶线的中间开始,这条线应该朝不同的方向走并改变颜色。
关于应该像这样工作,但它从顶部中间开始:
codepen.io
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" height="60" width="320" />
<div class="text">Hover me</div>
</svg>
</a>
</div>
</section>
【问题讨论】:
标签:
javascript
jquery
css
svg
【解决方案1】:
检查一下,现在这条线是顺时针方向的。
只需使用.rect-shape 的stroke-dasharray 和stroke-dashoffset 属性即可获得您最满意的效果:
stroke-dasharray: 140 620;
stroke-dashoffset: 274;
当然你可以设置正或负的 dashoffset 值,然后你就可以改变动画的方向
在官方页面这里举一个更详细的例子:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: #EB3349;
}
a, a:hover, a:focus, a:active, a:visited {
color: #fff;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: default;
}
.rect-shape {
stroke-dasharray: 130 620;
stroke-dashoffset: 274;
stroke-width: 8px;
fill: url(#gradient);
/* modify this with the color you want */
stroke: #fff;
transition: stroke-width 1s, stroke-dashoffset 1s, stroke-dasharray 1s;
}
.text {
font-family: serif;
font-size: 22px;
line-height: 32px;
letter-spacing: 4px;
color: #fff;
top: -48px;
position: relative;
text-align: center;
}
.svg-container:hover .rect-shape {
stroke-width: 2px;
stroke-dashoffset: 0;
stroke-dasharray: 760;
}
#gradient stop {
transition: .5s all;
}
.svg-container:hover svg.gradient #gradient stop:first-child {
stop-color: #EB3349;
}
.svg-container:hover svg.gradient #gradient stop:last-child {
stop-color: #f45c43;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" height="60" width="320" />
<div class="text">Hover me</div>
</svg>
</a>
</div>
</section>
【解决方案2】:
要实现使用两条线同时为绘图设置动画的想法,您可以使用stroke-dasharray 属性。 stroke-dasharray 属性有几个参数对:
stroke-dasharray =" dash space dash space "
剩下的就是计算这些参数的必要值:
按钮周长:320 + 60 + 320 + 60 = 760px
周长的一半 - 这将是一条线的长度 - 380 像素
要在绘制的初始阶段隐藏线条,请写stroke-dasharray = "0 380 0 380"
也就是说,一个破折号是0,一个空格是380,一个破折号是0,一个空格是380
总计:笔画长度 - 0,空格长度 - 760,即线条将被完全隐藏
要完全显示两条闭合线:stroke-dasharray = "0 0 760 0"
我们写动画公式:values = "0 380 0 380; 0 0 760 0"
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: #3A92CE;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="600" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Bottom middle</div>
</svg>
</a>
</div>
</section>
中上
要从另一个点开始动画,例如从按钮顶行的中间开始,你需要使用命令stroke-dashoffset = "220" 移动动画的起始点
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: #4A4A4A;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="220" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Top middle</div>
</svg>
</a>
</div>
</section>
左上角
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: #4A4A4A;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="380" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Top left</div>
</svg>
</a>
</div>
</section>
右上角
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: #3A92CE;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="60" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Top right</div>
</svg>
</a>
</div>
</section>
左下
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: purple;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="440" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Bottom left</div>
</svg>
</a>
</div>
</section>
右下角
body {
max-width: 100vh;
margin: 0;
color: #fff;
font-size: 24px;
background: purple;
}
a, a:hover, a:focus, a:active, a:visited {
color: gold;
text-decoration: none;
font-size: 1em;
}
.hero {
height: 100vh;
width: 100vw;
}
.svg-container {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
width: 320px;
max-height: 60px;
cursor: pointer;
}
.rect-shape {
stroke:#E4E4E4;
stroke-width:2;
fill:transparent;
}
.text {
font-family: serif;
font-size: 26px;
font-weight:bold;
line-height: 32px;
letter-spacing: 4px;
color: #E4E4E4;
top: -48px;
position: relative;
text-align: center;
}
<section class="hero">
<div class="svg-container">
<a class="magic-link" href="#">
<svg class="gradient" id="svg1" height="60" width="320" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#EB3349" />
<stop offset="95%" stop-color="#EB3349" />
</linearGradient>
</defs>
<rect class="rect-shape" id="rect1" height="60" width="320" stroke-width="2" />
<polyline id="p1" points="0 0, 320 0, 320 60, 0 60, 0 0" fill="transparent" stroke="#E4E4E4"
stroke-width="8" stroke-dashoffset="0" stroke-dasharray="0 380" >
<animate id="an1"
attributeName="stroke-dasharray"
values="0 380 0 380;0 0 760 0"
dur="1s"
begin="p1.mouseover"
fill="freeze"
restart="whenNotActive" />
<animate id="an2"
attributeName="stroke-dasharray"
values="0 0 760 0;0 380 0 380"
dur="0.5s"
begin="an1.end"
fill="freeze"
restart="whenNotActive" />
</polyline>
<div class="text">Bottom right</div>
</svg>
</a>
</div>
</section>