有趣的css

web菜青蟲發表於2018-04-17

如題:

如題

基本思路

將扇形拆分成三角,整個圓是6等分,即每個圓角60°,扇形所對應是一個等邊三角形,利用overflow:hidden,將等邊三角形裁剪成 扇形,實現了一個扇形,那其他的幾個進行旋轉。

我們肯定知道利用css的border來實現三角形,那麼如何實現一個等邊三角形呢?

基礎栗子:

.triangle {
  width: 0;
  height: 0;
  border-width: 10px 10px 10px 10px;
  border-style: solid;
  border-color: #ff0000 transparent transparent transparent;
}

複製程式碼

這樣會生成一個等腰直角三角形,頂角90°,顯然不滿足需求,但是我們也已經實現了一半,通過改變border-width,以達到60°腳。 結合三角函式,以及border生成三角形,我們把等邊三角形從頂角等分,分成兩個30°頂角的直角三角形,三角形短邊就是我們所設定的 border-width(具體怎麼算,嘗試一下就知道了)。那麼如題,需求是半徑100px,即我們60°所對應的直角邊就是100px,所以我們的border-width 就是r*cos(30°),這樣我們的等邊三角形就出來了(因為cos(30°)所得到的只能是一個近似值,所以這樣做出來的肯定是有誤差的)。

方案一

畫出一個等邊三角形,複製6個,然後每個一次多旋轉60°,最後湊成原型。

    <div class="circle-box1">
      <div class="item nth-0"></div>
      <div class="item nth-1"></div>
      <div class="item nth-2"></div>
      <div class="item nth-3"></div>
      <div class="item nth-4"></div>
      <div class="item nth-5"></div>
    </div>

複製程式碼
$r: 100px;
$sin60: 0.866;
$borwid: $r / $sin60 / 2;
.circle-box1 {
  width: 200px;
  height: 200px;
  margin: 50px auto;
  position: relative;
  border-radius: 100%;
  overflow: hidden;
  background: #ff0000;
  .item {
    width: 0;
    height: 0;
    border-width: $r $borwid 0 $borwid;
    border-style: solid;
    border-color: #ff0 transparent transparent transparent;
    position: absolute;
    left: $r - $borwid;
    top: 0;
    transform-origin: 50% 100%;
    &:nth-child(2n + 1) {
      border-color: #333 transparent transparent transparent;
    }
    @for $i from 0 through 5 {
      &.nth-#{$i} {
        transform: rotate(60deg * $i)
      }
    }
  }
}

複製程式碼

方案二

方案一的優化版,在上述的例子中,如果四邊都不是透明的話,我們可以形成四個等腰直角三角形,所以現在改成兩個對角的等邊三角形。

    <div class="circle-box2">
      <div class='circle'>
      </div>
    </div>
複製程式碼
$r: 100px;
$sin60: 0.866;
$borwid: $r / $sin60 / 2;
.circle-box2 {
  width: 200px;
  height: 200px;
  text-align: center;
  margin: 50px auto;
  border-radius: 100%;
  overflow: hidden;
  background: #ff0000;
  .circle {
    display: inline-block;
    width: 0;
    height: 0;
    border-width: $r $borwid $r $borwid;
    border-style: solid;
    border-color: #333 transparent #ff0 transparent;
    position: relative;
    box-sizing: border-box;
    &:before {
      content: '';
      display: block;
      width: 0;
      height: 0;
      border-width: $r $borwid $r $borwid;
      border-style: solid;
      border-color: #ff0 transparent #333 transparent;
      position: absolute;
      left: -$borwid;
      top: -$r;
      transform: rotate(60deg)
    }
    &:after {
      content: '';
      display: block;
      width: 0;
      height: 0;
      border-width: $r $borwid $r $borwid;
      border-style: solid;
      border-color: #ff0 transparent #333 transparent;
      position: absolute;
      left: -$borwid;
      top: -$r;
      transform: rotate(-60deg)
    }
  }
}
複製程式碼

方案三

方案三借鑑圈友發的大漠的一個例子。與原方案不相同的是,這個扇形是通過將圓形進行遮罩而實現的,再通過clip進行裁剪。

    <div class="circle-box3">
      <div class="circle"></div>
      <div class="circle turn"></div>
    </div>
複製程式碼
.circle-box3 {
  width: 200px;
  height: 200px;
  margin: 50px auto;
  position: relative;
  background: #ff0000;
  border-radius: 100%;
  overflow: hidden;
  .circle {
    width: 200px;
    height: 200px;
    position: absolute;
    left: 0;
    top: 0;
    border-radius: 100%;
    overflow: hidden;
    clip: rect(0, $r * 2, $r, 0);
    &.turn {
      transform: rotateX(180deg);
      &:before {
        background-image: linear-gradient(60deg, #333 50%, #ff0 0);
      }
      &:after {
        background-color: #333;
      }
    }
    &:before{
      content: '';
      display: block;
      width: 100%;
      height: 100%;
      background: #ff0;
      background-image: linear-gradient(60deg, #ff0 50%, #333 0);
      position: absolute;
      left: 0;
      top: 0;
    }
    &:after {
      content: '';
      display: block;
      width: 100%;
      margin-left: 50%;
      height: 100%;
      background-color: #ff0;
      transform-origin: left;
      transform: rotate(30deg);
      position: absolute;
      left: 0;
      top: 0;
    }
  }
}
複製程式碼

裡面有幾個需要注意的點:

  1. css transform-origin 定義旋轉的中心點

  2. clip rect(top, right, bottom, left),其中需要注意的是right和bottom,這裡面的值都是基於左上角來算的。

  3. css 線性漸變 linear-gradient

  4. css transform: rotate() 基於某軸的旋轉

總結

在實現之前其實已經想到,也就是上面的那個近似值問題,在渲染的時候,也包括計算的時候,方案一二形成的三角形的60°只能說近似60°, 導致的結果是扇形之間是有間隙的,所以上面的程式碼中,在包圍盒設定了紅色背景,為了突出間隙,可通過將背景色設定的與扇形顏色一樣解決該問題。

方案三種的實現,可能遠離上麻煩一點,但是這裡畫出來的60°角可以認為是基本準確的。從html結構來說,也相對較好。

css的世界裡面,有著各種技巧,所以方案應該也不止這三種。奈何博主本人技能有限,歡迎大神給出更好的方案。

補充

額,很尷尬的是忘記了題目上的絕對居中需求,絕對居中的方案有很多,這裡就不介紹啦~~~

原文連結

相關文章