跳到主要內容
黯羽輕揚每天積累一點點

用 Sass 畫蝸牛

免費2015-05-12#CSS#纯css画图#用css画

最近起了個藝名,叫小蝸。剛好又接觸了 Sass,就拿來練練手。

一.Sass 的好處

用 CSS 畫圖也算是簡單的實戰吧,雖然用到的東西還比較少...用過之後,發現 Sass 主要有以下優勢:

  1. 可維護性。最重要的一點,可維護性的很大一部分來自變量

嗯,最簡單的例子,畫圖總要有前景色背景色填塗色等等一堆色值吧,用 CSS 也可以完成,但如果要修改某個填塗色可能需要先審查元素找到具體色值,再對源碼 Ctrl + H 全文替換一遍才行。用 Sass 的話就沒這麼麻煩了,簡單地改下變量的值,輕鬆搞定,沒錯,根本不用審查元素找色值那麼麻煩,因為好的變量名肯定是自解釋的

  1. 易用性。剛剛入門用起來都很順手

兼容 CSS 語法,在此基礎上提供擴展功能,用起來非常順手。比如嵌套結構表示後代選擇器,使用方便,容易理解,還能避免一些書寫錯誤

  1. 靈活性。難以置信的靈活

@mixin 提供了極大的靈活性,無參、多參、可選參、任意多參要比很多編程語言更加靈活,入口靈活不僅有利於代碼複用,還讓接口變得更加易用(不需要記一堆功能相似的函數名)

無意中發現了一個很靈活的用法,代碼如下:

    // 如果只想簡單地支持 1 參數和 4 參數形式,可以這樣實現
    @mixin radius ($r1, $r2: $r1, $r3: $r1, $r4: $r1) { // 注意把默認值設置為了其它形參的值,這太靈活了
      // 作為例子就不考慮兼容性了
      border-radius: $r1 $r2 $r3 $r4;
    }

    // 如果想實現 0 冗餘和支持 1、2、3、4 參數形式,可以這樣實現
    @mixin radius2 ($r...) {    // 類似於 c++ 的語法
      $argNum: length($r);
      
      @if ($argNum == 1) {      // 1 參
        border-radius: nth($r, 1);
      }
      @else if ($argNum == 2) { // 2 參
        border-radius: nth($r, 1) nth($r, 2);
      }
      @else if ($argNum == 3) { // 3 參
        border-radius: nth($r, 1) nth($r, 2) nth($r, 3);
      }
      @else { // 4 參,再多就只取前 4 個
        border-radius: nth($r, 1) nth($r, 2) nth($r, 3) nth($r, 4);
      }
    }

    // 測試
    h1 {
      @include radius(1px);
      @include radius(1px, 2px, 3px, 4px);
      
      @include radius2(1px);
      @include radius2(1px, 2px);
      @include radius2(1px, 2px, 3px);
      @include radius2(1px, 2px, 3px, 4px);
    }
    

生成的 CSS 代碼如下:

    h1 {
      border-radius: 1px 1px 1px 1px;
      border-radius: 1px 2px 3px 4px;
      border-radius: 1px;
      border-radius: 1px 2px;
      border-radius: 1px 2px 3px;
      border-radius: 1px 2px 3px 4px;
    }
    

4. 可複用性。畫過蝸牛後,畫青蛙什麼的將會很快

畫蝸牛只是一個很簡單很獨立的「項目」(額,麻雀雖小。。),所以創建了很多工具函數(@mixin),而大多數工具函數都是可以複用的,用來畫青蛙、畫麻雀。。當然,肯定不會局限於畫畫,別的地方也能用

比如,可以有一個自動添屬性名前綴的 @mixin:

    // 帶瀏覽器前綴的屬性設置
    @mixin attr ($name, $value) {
      #{$name}: $value; // 注意左邊要添上#{},否則就是賦值了
      /* Firefox */
      -moz-#{$name}: $value;
      /* IE */
      -ms-#{$name}: $value;
      /* Opera */
      -o-#{$name}: $value;
      /* WebKit */
      -webkit-#{$name}: $value;
    }

5. 自解釋性。或者說是語義上的好處

變量名、@mixin 名、@function 名都可以語義化,如果是 CSS 就不得不添加一堆註釋去解釋。自解釋的東西,不僅對自己好,將來對別人也好

二.畫圖

小蝸原圖:

蝸牛

很簡單的小蝸牛,除了圈還是圈,以前用 div 角角的 1px 拼這個不現實,但有了 border-radius 後,曲線什麼的,太容易了

1.分解線條

用 CSS 畫圖,第一步肯定是把圖中的線條分解成 div(div 比 span 有更大的自由度,而且沒有語義,正適合幹這個),說白了就是寫 HTML

一般規則從上到下、從左向右分解,每條線對應一個 div 就好了,這樣分解可以很大程度上避免出現margin-left: -30px;之類的東西,讓代碼更具可讀性

分解結果:

<!-- HTML 結構 -->
<div class="wrapper">
    <!-- 小蝸整體 -->
    <div class="xiaowo">
        <!-- 頭部 -->
        <div class="head">
            <!-- 眼睛-->
            <div class="eyes">
                <!-- 左眼 -->
                <div class="eye left">
                    <!--眼珠-->
                    <div class="black bleft"></div>
                </div>
                
                <!-- 短橫線 -->
                <div class="shortHLine">
                </div>
                
                <!-- 右眼 -->
                <div class="eye right">
                    <div class="black bright"></div>
                </div>
                
                <!-- 短斜線 -->
                <div class="shortSlash">
                </div>
                
                <!-- 嘴巴 -->
                <div class="mouth">
                </div>
            </div>
        </div>
        
        <!-- 殼兒 -->
        <div class="shell">
            <!-- 內圈 -->
            <div class="innerCircle">
                <!-- 最內圈 -->
                <div class="innerinnerCircle">
                </div>
            </div>
        </div>
        
        <!-- 右邊身體 -->
        <div class="rbody">
        </div>
        
        <!-- 底部身體 -->
        <div class="bbody">
            <!-- 左邊短弧線 -->
            <div class="shortArc">
            </div>
            
            <!-- 底部長弧線 -->
            <div class="longArc">
            </div>
        </div>
    </div>
</div>

P.S.具體怎麼分解,並沒有太大關係,一個線條對應一個 div,肯定只多不少,不妨先這樣做,到時候如果發現多餘了再刪掉就好

2.寫 Sass

有了 HTML 結構就可以直接開始寫樣式了,規則是從外到內、從左向右一點一點寫

很簡單,只是需要些耐心,1 個像素 1 個像素、一遍一遍地調試

成品 Sass 代碼如下:

/*!
 * 小蝸 - sass
 */

// 變量
$fc: #2b2b2b;
$bc: #fafafa;
$bWidth: 7px;
$bStyle: solid;
$bColor: #2b2b2b;
// 此處透明色不考慮 IE 兼容,因為 IE6 下很難畫出曲線邊框,透明也沒什麼意義
$hidden: transparent;
$border: $bWidth $bStyle $bColor;
$_border: $bWidth $bStyle $hidden;

// 混合
// 0 ~ 無,1 ~ borderStyle,-1 ~ transparent
@mixin border($t, $r, $b, $l) {
  @if ($t == 1) {
    border-top: $border;
  }
  @else if ($t == -1) {
    border-top: $_border;
  }
  
  @if ($r == 1) {
    border-right: $border;
  }
  @else if ($r == -1) {
    border-right: $_border;
  }
  
  @if ($b == 1) {
    border-bottom: $border;
  }
  @else if ($b == -1) {
    border-bottom: $_border;
  }
  
  @if ($l == 1) {
    border-left: $border;
  }
  @else if ($l == -1) {
    border-left: $_border;
  }
}

// 簡單起見,只支持 1 個參數或者 4 個參數形式
@mixin radius ($r...) {
  @if (length($r) == 1) {
    border-radius: nth($r, 1);
    /* Firefox */
    -moz-border-radius : nth($r, 1);
    /* IE */
    -ms-border-radius : nth($r, 1);
    /* Opera */
    -o-border-radius : nth($r, 1);
    /* WebKit */
    -webkit-border-radius : nth($r, 1);
  }
  @else {
    $r1: nth($r, 1);
    $r2: nth($r, 2);
    $r3: nth($r, 3);
    $r4: nth($r, 4);
    border-radius: $r1 $r2 $r3 $r4;
    /* Firefox */
    -moz-border-radius : $r1 $r2 $r3 $r4;
    /* IE */
    -ms-border-radius : $r1 $r2 $r3 $r4;
    /* Opera */
    -o-border-radius : $r1 $r2 $r3 $r4;
    /* WebKit */
    -webkit-border-radius : $r1 $r2 $r3 $r4;
  }
}

@mixin transform ($deg) {
  transform: rotate($deg);
  // IE 9
  -ms-transform:rotate($deg);
  // Firefox
  -moz-transform:rotate($deg);
  // Safari and Chrome
  -webkit-transform:rotate($deg);
  // Opera
  -o-transform:rotate($deg);
}

// 盒子
.wrapper{
  margin: 10px 0 0 30px;
}

// 小蝸
.xiaowo{
  position: relative;
  
  // 頭部
  .head {
    position:relative;
    z-index: 100;
    margin-left: 200px;
    width: 232px;
    height: 125px;
    background-color: $bc;
  }
  
  // 眼睛
  .eyes{
    position: relative;
  }
  .eye{
    position: absolute;
    width: 100px;
    height: 105px;
    @include radius(57px);
    border: $border;
  }
  // 左眼
  .left{
    top: 10px;
    left: -3px;
  }
  // 眼珠
  .black{
    position: absolute;
    background-color: #000; // 炯炯有神的黑眼珠
    width: 30px;
    height: 32px;
    @include radius(15px);
  }
  // 左眼珠 */
  .bleft{
    top: 25px;
    left: 40px;
  }
  // 短橫線
  .shortHLine{
    position: absolute;
    top: 60px;
    left: 110px;
    width: 12px;
    @include border(0, 0, 1, 0);
  }
  // 右眼
  .right{
    top: 7px;
    right: 0;
  }
  // 右眼珠
  .bright{
    top: 25px;
    left: 40px;
  }
  
  // 短斜線
  .shortSlash{
    position: absolute;
    top: 125px;
    left: 32px;
    width: 30px;
    height: 30px;
    border-left: 7px solid #2b2b2b;
    @include transform(20deg);
  }
  
  // 嘴巴
  .mouth{
    position: absolute;
    top: 130px;
    left: 92px;
    width: 50px;
    height: 24px;
    @include border(0, 1, 1, 1);
    @include radius(0, 0, 30px, 32px);
  }
  
  // 殼兒
  .shell{
    position: absolute;
    top: 75px;
    width: 300px;
    height: 300px;
    @include radius(157px);
    @include border(1, -1, 1, 1);
  }
  // 內圈
  .innerCircle{
    position: absolute;
    top: 55px;
    left: 50px;
    width: 230px;
    height: 230px;
    @include radius(122px);
    @include border(1, 1, -1, 1);
  }
  // 最內圈
  .innerinnerCircle{
    position: absolute;
    top: 55px;
    left: 75px;
    width: 80px;
    height: 80px;
    @include radius(47px);
    border: $border;
  }
  
  // 右邊身體
  .rbody{
    position: absolute;
    top: 60px;
    left: 0px;
    width: 410px;
    height: 345px;
    @include border(-1, 1, -1, -1);
    @include radius(0, 170px, 137px, 0);
  }
  
  // 底部身體
  .bbody{
    position: absolute;
    top: 317px;
    left: 0;
    width: 300px;
    height: 100px;
  }
  // 左邊短弧線
  .shortArc{
    position: absolute;
    top: 30px;
    left: 27px;
    width: 36px;
    height: 36px;
    @include border(1, -1, -1, 1);
    @include radius(25px);
  }
  // 底部長弧線
  .longArc{
    position: absolute;
    top: -248px;
    left: -5px;
    width: 415px;
    height: 345px;
    @include border(-1, 1, 1, -1);
    @include radius(900px, 630px, 605px, 527px);
  }
}

3.修繕

具體工作是:

  1. 去除多餘線條

用類似於border-bottom: 5px solid transparent;的代碼去掉多餘線條,注意不能用border-bottom: 0;來消除,因為底邊寬度為 0 會影響其它邊(border-radius 是連邊框寬度一起算的)

  1. 拼接曲線

去掉多餘線條後肯定會出現斷開的線條,需要重新定位讓曲線完美地接起來

  1. 微調

接好後再調調比例、寬高、彎曲程度什麼的,就更完美了

三.運行結果

sass 小蝸

P.S.可能你也發現了,其實 Sass 並不適合幹這個,畫圖時的調試是直接針對 CSS 的,把 Sass 扯進來反而更麻煩了。。這都沒關係,拿到把新錘子總想用用,現在如願了

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論