メインコンテンツへ移動

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 を書くことです

一般的なルールは上から下へ、左から右へ分解し、各線が 1 つの 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.具体的にどう分解するかはあまり重要ではありません。1 つの線が 1 つの div に対応すれば、きっと多すぎることはありません。まずこうしておいて、後で余分だとわかったら削除すればよいのです

###2.Sass を書く

HTML 構造ができたら、直接スタイルを書き始められます。ルールは外から内へ、左から右へ少しずつ書くことです

非常にシンプルで、忍耐が必要ですが、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 を持ち込むとむしろ面倒になります。。それでも関係ありません。新しいハンマーを手に入れたら使ってみたくなるもので、今は如愿しました

###参考資料

コメント

コメントはまだありません

コメントを書く