酷酷的SVG动画菜单
SVG动画,结合了CSS3的transition, 先看下效果图 动画效果: 直接参见本页面的导航菜单鼠标一上去,会有border变长,通过border的dashoffset的变化,包围住整个菜单矩形。用到了css3的animation,详细用法大家可以看下: http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html 讲的比较好注意,Firefox中跟webkit计算dash-offset方法有不同,需要fix一下:/** * FIX Firefox bugs: an
SVG动画,结合了CSS3的transition, 先看下效果图
动画效果: 直接参见本页面的导航菜单
鼠标一上去,会有border变长,通过border的dashoffset的变化,包围住整个菜单矩形。
用到了css3的animation,详细用法大家可以看下: http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html 讲的比较好
注意,Firefox中跟webkit计算dash-offset方法有不同,需要fix一下:
/**
* FIX Firefox bugs: anti-direcion,
* and dashoffset is different with Chrome
*/
@keyframes moz_draw {
0% {
stroke-dasharray: $dash_len $dash_space_len;
stroke-dashoffset: $dash_offset;
stroke-width: $stroke_max_width;
}
100% {
stroke-dasharray: $dash_full_len+$dash_space_len;
stroke-dashoffset: -$dash_offset;
stroke-width: $stroke_min_width;
}
}
然后单独对Firefox进行CSS Hack:
&:hover .shape {
-webkit-animation: 0.5s linear 0s normal forwards 1 draw;
animation: 0.5s linear 0s normal forwards 1 draw;
//fix Firefox :stroke-dashoffset not 0 ??
@-moz-document url-prefix() {
animation: 0.5s linear 0s normal forwards 1 moz_draw;
}
}
Firefox的差异,稍后有时间我再研究下。这种东西比较坑爹~
其他不多说,上代码,算法代码总有注释:
1. 先上html结构参考:
<header>
<nav>
<div class="menu active">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="180px" height="48px">
<rect width="180px" height="48px" class="shape"></rect>
</svg>
<a href="/" class="text">HOME</a>
</div>
<div class="menu">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="180px" height="48px">
<rect width="180px" height="48px" class="shape"></rect>
</svg>
<a href="/toxic" class="text">TOXIC</a>
</div>
<div class="menu">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="180px" height="48px">
<rect width="180px" height="48px" class="shape"></rect>
</svg>
<a href="/gallery" class="text">GALLERY</a>
</div>
</nav>
</header>
2. 这块是定义变量和动画, 注意下stroke和dash、dash offset的值的定义:
@import 'define';
@import 'util';
/**
* Stroke Calculator =====================
* @type {[type]}
* @description: stroke-dashoffset ,
* 是起点偏移量,在svg的rect中,从左上角开始,
* 如果offset为负值,那么线段向右偏移移动。
* dasharray第一个是线段长度,
* 第二个是空白间隔长度,
* 当空白间隔小于 offset的时候,
* 起点处会进入一部分线段(起点之前的线段)。
* 线段是无穷循环的,
* 但是都会没入结点中,超过结点后,被覆盖。
*/
$stroke_color: #19f6e8;
$menu_w: 180px;
$menu_h: 48px;
$stroke_max_width: 6px;
$stroke_min_width: 2px;
$dash_len: 120px;
$dash_space_len: $menu_w + $menu_h + ($menu_w - $dash_len)/2;
$dash_offset: - $dash_space_len;
$dash_full_len: 2*($menu_w + $menu_h);
//======================================
/**
* A text center size
*/
$text_size: 18px;
$text_bottom: $text_size + ($menu_h - $text_size)/2 + $stroke_min_width;
@keyframes draw {
0% {
stroke-dasharray: $dash_len $dash_space_len;
stroke-dashoffset: $dash_offset;
stroke-width: $stroke_max_width;
}
100% {
stroke-dasharray: $dash_full_len;
stroke-dashoffset: 0;
stroke-width: $stroke_min_width;
}
}
/**
* FIX Firefox bugs: anti-direcion,
* and dashoffset is different with Chrome
*/
@keyframes moz_draw {
0% {
stroke-dasharray: $dash_len $dash_space_len;
stroke-dashoffset: $dash_offset;
stroke-width: $stroke_max_width;
}
100% {
stroke-dasharray: $dash_full_len+$dash_space_len;
stroke-dashoffset: -$dash_offset;
stroke-width: $stroke_min_width;
}
}
3. 这块是CSS样式
.menu {
width: $menu_w;
height: $menu_h;
display: inline-block;
margin: 2px;
// margin: 0 auto;
text-align: center;
position: relative;
/**
* @debug Firefox和一些safair版本中,不识别CSS中的width和height
* 必须将width写在svg代码中
*/
svg{
width: $menu_w;
height: $menu_h;
.shape {
// @extend .hardware;
width: $menu_w;
height: $menu_h;
fill: transparent;
stroke-dasharray: $dash_len $dash_space_len;
stroke-dashoffset: $dash_offset;
stroke-width: 0;
stroke: $stroke_color;
// 选中状态的
@at-root nav .menu.active svg .shape {
stroke-width: $stroke_max_width;
}
}
}
&:hover .shape {
-webkit-animation: 0.5s linear 0s normal forwards 1 draw;
animation: 0.5s linear 0s normal forwards 1 draw;
//fix Firefox :stroke-dashoffset not 0 ??
@-moz-document url-prefix() {
animation: 0.5s linear 0s normal forwards 1 moz_draw;
}
}
.text {
// 具有子菜单的一级菜单,具有交互模糊效果
@at-root .menu.on .text{
@include blur(2px);
}
@include trans-all();
color: $nav_a_color;
font-size: $text_size;
letter-spacing: 3px;
line-height: $text_size;
position: relative;
bottom: $text_bottom;
// font-family: 'roboto';
text-decoration: none;
&:hover {
color: $nav_a_color;
letter-spacing: 4px;
}
}
}