在慕課網發現了一個有意思的課程,叫 數學知識在CSS動畫中的應用 。用到的數學知識是如何計算圓上每一個點的座標。統一名稱,中間的菜單叫觸發菜單,四周發散的菜單叫子菜單,css
效果預覽html
慕課網經過jquery計算子菜單的座標,控制相應的css屬性,來實現這一功能。
有關計算,又有關css屬性,那麼css預處理器即是一個不錯的選擇。node
scss基於ruby,使用在服務器端。less基於node,能夠直接在瀏覽器端使用,但會消耗更多的性能。因此二者通常都會在前期使用工具編譯爲css。scss不支持三角函數,less卻可以很好的支持三角函數,less便成了一個不錯的選擇。jquery
先把大體佈局放在這裏。git
<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>
把徑向菜單置於窗口中間,能夠使用絕對定位,而後使它居中。寫一個MIXINgithub
.center() { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
如下mixin表示一個以@radius
爲半徑,@color
爲背景的一個圓。圓是一個圓角半徑爲50%的正方形。box-sizing: border-box
使得能夠給圓添加邊框長度而不至於使圓變形。瀏覽器
.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
控制字體居中。ruby
.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
設置背景,使它看起來像一個按鈕。服務器
.btn, .toggle { .radius(@toggle-radius, rgb(0, 51, 51)); .center(); } .toggle { opacity: 0; cursor: pointer; &:checked { .generate-circle(); } }
點擊觸發菜單會使子菜單發散開來。此時子菜單的選擇器應該使用~
選擇器。計算其位置設置translate的平移屬性,並設置動畫。
less使用循環生成每一個子菜單的位置,count是子菜單的數量。不得不說,仍是scss的for循環好用太多。less
注意其下用的是nth-of-type
。
.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); }