본문으로 건너뛰기

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 픽셀씩,一次又一次 디버그합니다

완성된 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 를 끌어들이면 오히려 더 번거로워집니다.. 그래도 상관없습니다. 새로운 망치를 손에 넣으면 사용하고 싶어지는 법이며, 지금은 소원을 이뤘습니다

###참고 자료

댓글

아직 댓글이 없습니다

댓글 작성