在慕课网发现了一个有意思的课程,叫 数学知识在CSS动画中的应用 。用到的数学知识是如何计算圆上每个点的坐标。统一名称,中间的菜单叫触发菜单,四周发散的菜单叫子菜单。
慕课网通过jquery计算子菜单的坐标,控制相应的css属性,来实现这一功能。
有关计算,又有关css属性,那么css预处理器便是一个不错的选择。
效果预览
less与scss
scss基于ruby,使用在服务器端。less基于node,可以直接在浏览器端使用,但会消耗更多的性能。所以两者一般都会在前期使用工具编译为css。scss不支持三角函数,less却能够很好的支持三角函数,less便成了一个不错的选择。
先把大致布局放在这里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <div class="container"> <a class="btn"></a> <input type="checkbox" class="toggle"> <div class="circle">1</div> <div class="circle">2</div> <div class="circle">3</div> <div class="circle">4</div> <div class="circle">5</div> <div class="circle">6</div> <div class="circle">7</div> <div class="circle">8</div> <div class="circle">9</div> <div class="circle">10</div> <div class="circle">11</div> <div class="circle">12</div> </div>
|
绝对定位居中
把径向菜单置于窗口中间,可以使用绝对定位,然后使它居中。写一个MIXIN
1 2 3 4 5 6
| .center() { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
画一个圆
以下mixin表示一个以@radius
为半径,@color
为背景的一个圆。圆是一个圆角半径为50%的正方形。box-sizing: border-box
使得可以给圆添加边框长度而不至于使圆变形。
1 2 3 4 5 6 7
| .radius(@radius, @color: transparent) { width: @radius * 2; height: @radius * 2; border-radius: 50%; background-color: @color; box-sizing: border-box; }
|
设置径向菜单大小及初始位置
.container
表示子菜单所在的圆,.circle
为子菜单,初始化时无大小,text-align
与line-height
控制字体居中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .container { .center(); .radius(@distance); border: 1px dotted #aaa; }
.circle { .radius(0); .center(); font-size: 0; opacity: 0; transition: all 800ms ease; line-height: @circle-radius * 2; text-align: center; color: #ffc; cursor: pointer; }
|
触发菜单
点击触发菜单会使子菜单发散。checkbox
通过:checked
伪类选择器可以模拟点击触发的效果,使它的透明度改为0,再增加一个装饰的.btn
设置背景,使它看起来像一个按钮。
1 2 3 4 5 6 7 8 9 10 11 12 13
| .btn, .toggle { .radius(@toggle-radius, rgb(0, 51, 51)); .center(); }
.toggle { opacity: 0; cursor: pointer; &:checked { .generate-circle(); } }
|
子菜单的发散
点击触发菜单会使子菜单发散开来。此时子菜单的选择器应该使用~
选择器。计算其位置设置translate的平移属性,并设置动画。
less使用循环生成每个子菜单的位置,count是子菜单的数量。不得不说,还是scss的for循环好用太多。
注意其下用的是nth-of-type
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| .generate-circle(@i: 1) when (@i < @count + 1) { & ~ .circle:nth-of-type(@{i}) { .radius(@circle-radius, @color); @top: round(sin(pi() * 2 * (@i - 1)/ @count) * @distance) - @circle-radius; @left: round(cos(pi() * 2 * (@i - 1)/ @count) * @distance) - @circle-radius; transform: translate(@top, @left); opacity: 1; font-size: 1em; transition: all 800ms ease; &:hover { background-color: #033; } } .generate-circle(@i + 1); }
|
源码
使用less做的径向菜单
效果预览
参考
less语言特性
再谈 CSS 预处理器
数学知识在CSS动画中的应用