[TIL] 2021 01 08 Fri

1. Javascript 30

Day 7 : Array Cardio Day 2

이번에도 간단한 배열 메소드를 연습하는 프로젝트.
some, every, find, findIndex 메소드 사용

Day 8 : Fun with HTML5 Canvas

선을 그릴 때마다 색깔과 선 두께가 바뀌는 HTML 캔버스 구현 프로젝트.

1. canvas 태그

<canvas id="draw" width="800" height="800"></canvas>

canvas 태그의 속성은 width와 height 뿐(디폴트 300px, 150px)이며 DOM을 통해서 추후 조절이 가능하다.
또 주의할 것! canvas는 셀프클로징이 불가능한 태그라고 한다. 닫는 태그</canvas>가 꼭 필요! -> 캔버스를 지원하지 않는 브라우저에는 canvas 태그 안에 img 태그 등을 임의로 넣어줄 수 있다.

2. context 생성

캔버스 태그가 랜더링 영역을 지정해준다면, context는 컨텐츠의 출력 및 렌더링을 담당한다고 한다. getContext()라는 메소드를 사용하여 선언할 수 있으며, 인자로 '2d', '3d'를 지정해줄 수 있다. (webGL의 경우가 "3d")

const canvas = document.querySelector("#draw");

// 캔버스의 크기 설정하기
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// 2d 렌더링 컨텍스트 설정하기
const ctx = canvas.getContext("2d");

// 선의 모양 설정하기
ctx.strokeStyle = "#BADA55"; /* 선의 색, 그라디언트, 패턴 등을 결정 */
ctx.lineJoin = "round"; /* 두 선이 만났을 때 접점을 둥글게 처리 */
ctx.lineCap = "round"; /* 선 끝을 둥글게 */
ctx.lineWidth = 100; /* 선의 두께 */

3. 그리기

let isDrawing = false; /* isDrawing state */
let lastX = 0; /* 시작점의 x좌표 설정 */
let lastY = 0; /* 시작점의 y좌표 설정 */

function draw(e) {
  if (!isDrawing) return;
  ctx.beginPath(); /* 경로를 그리기 시작 */
  ctx.moveTo(lastX, lastY); /* 경로를 그리지 않고 해당 좌표로 이동 : 시작점*/
  ctx.lineTo(e.offsetX, e.offsetY); /* 경로를 그리며 이동 : 끝점 */
  ctx.stroke(); /* 지정한 경로에 실제로 선을 남김 */
  
  lastX = e.offsetX; /* 그리기가 끝난 시점에 다음 시작점의 x좌표 설정 */
  lastY = e.offsetY; /* 그리기가 끝난 시점에 다음 시작점의 y좌표 설정 */
}

canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mousedown", (e) => {
  isDrawing = true; /* isDrawing state 변경 */
  lastX = e.offsetX; /* drawing 시작점의 x좌표 설정 */
  lastY = e.offsetY; /* drawing 시작점의 y좌표 설정 */
});
canvas.addEventListener("mouseup", () => (isDrawing = false));
canvas.addEventListener("mouseout", () => (isDrawing = false));

4. 색깔과 선 두께 바꾸기


hsl은 hue(색상), saturation(채도), lightness(명도)를 모두 바꿀 수 있는 메소드이다.
hue는 0부터 360까지의 스펙트럼(빨강 ~ 보라)을 가지고, saturationlightness는 0에서 100%까지의 스펙트럼을 가진다. saturation의 기본값은 100%, lightness는 50%인 듯?

let hue = 0; 
let direction = true; /* 선 두께를 변경하기 위한 flag 역할 */

function draw(e) {
 /* ...위 코드에 이어서 계속... */
  
  hue++; /* 드로잉이 진행되는 동안 hue를 지속적으로 변경한다. */
  if (hue >= 360) hue = 0; /* hue는 360까지이므로 다시 0으로 리셋 */
  
  /* 선 두께를 0 ~ 100까지 조절하기 위한 flag */
  if (ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
    direction = !direction;
  }
  direction ? ctx.lineWidth++ : ctx.lineWidth--;
}

참고자료

2. Advanced CSS and Sass Flexbox, Grid, Animations and More!

section 5: Natours Project — Using Advanced CSS and Sass (Part 2)

1. 순수 CSS로 배경사진 위에 도형 덮기


background-image 속성에 가장 마지막 인자로 이미지 url을 넣으면 배경사진이 가장 마지막에 위치하게 된다.
그 위로 linear-gradient 효과를 주는데, 같은 %를 준다면 그 경계가 그라디언트가 아니라 면으로 나누어지는 효과를 활용하면 된다.

<div class="book"></div>
.book {
  background-image: 
    linear-gradient(
      105deg, /* 각도 조절! */
      rgba($color-white, 0.9) 0%, /* 0 ~ 50%을 하얀색으로 */
      rgba($color-white, 0.9) 50%, /* 50%라는 숫자가 겹치므로 경계는 면이 된다 */
      transparent 50% /* 나머지를 투명색으로 */
    ),
    url("../img/nat-10.jpg"); /* 배경이미지는 가장 마지막으로 */
}

2. input validation check

순수 html form 태그에서도 validation check가 가능하다는 걸 오늘 알았다.

<input type="text" class="form__input" required />

이렇게 required 속성을 주면 된다!

.form__input:focus:invalid {
  border-bottom: 3px solid $color-secondary-dark;
}

그리고 css에서 :focus:invalid를 설정하면 validation에 따른 스타일 설정이 가능하다.

3. 형제(동위) 셀렉터 (Sibling Combinator)

  • 인접 형제 셀렉터(Adjacent Sibling Combinator) : 셀렉터A의 형제 요소 중 셀렉터A 바로 뒤에 위치하는 셀렉터B 요소를 선택한다. A와 B 사이에 다른 요소가 존재하면 선택되지 않는다
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
/* 인접한 형제기 때문에 가능 */
.one + .two {
  display: block;
} 

/* 인접한 형제가 아니기 때문에 불가능 */
.one + .three {
  display: block;
} 
  • 일반 형제 셀렉터(General Sibling Combinator) : 셀렉터A의 형제 요소 중 셀렉터A 뒤에 위치하는 셀렉터B 요소를 모두 선택한다.
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
/* one two three 모두 선택 */
.one ~ .three {
  display: block;
} 

참고자료

4. radio input 커스텀하기


라디오 버튼은 브라우저 자체 디자인이기 때문에 커스텀이 불가능해서 "display: none"으로 숨기고 임의의 span 태그를 디자인하는 꼼수를 배웠다!

<div class="form__radio-group">
  <input type="radio" name="tour" id="small" class="form__radio-input"/>
  <label for="small" class="form__radio-label">
    <!--👇 요 친구가 가짜 라디오 버튼. label 안에 넣었기 때문에 input과 함께 묶인다 -->
    <span class="form__radio-button"></span> 
    Small tour group
  </label>
</div>
.form {
  /* 진짜 라디오버튼은 숨긴다 */
  &__radio-input {
    display: none; 
  }
  
  &__radio-label {
    position: relative;
  }
  
  /* 임의의 라디오버튼 디자인 (테두리) */
  &__radio-button { 
    height: 3rem;
    width: 3rem;
    border: 5px solid $color-primary;
    border-radius: 50%;
    display: inline-block;
    position: absolute;
    left: 0;
    top: -0.4rem;
    
    /* 임의의 라디오버튼 디자인 (select 시 나타나는 동그라미) */
    &::after {
      content: "";
      display: block;
      height: 1.3rem;
      width: 1.3rem;
      border-radius: 50%;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: $color-primary;
      opacity: 0;
      transition: opacity 0.2s;
    }
  }
  
  /* Sibling을 통해 input이 check 속성이 되었을 때 그 속성을 넘겨받는다 */
  &__radio-input:checked ~ &__radio-label &__radio-button::after {
    opacity: 1;
  }
}

3. 포트폴리오 구상 중

오늘은 집중이 잘 안 돼서 코드보다는 웹 포트폴리오 구상에 집중했다. 처음에는 이력서 양식을 계승한 포트폴리오를 만드려고 헀는데, 그럼 그냥 이력서를 pdf로 보는게 낫지 웹사이트로 보는 게 무슨 의미가 있지? 이런 생각이 들어서 색다른 시도를 해보기로 헀다. 인터렉티브까지는 되지 않더라도 최대한 playground처럼 꾸며보기로 했다. 나 자신을 표현하는 공간 그 자체로. 단순한 이력서가 아니라.

일단 구상하면서 도메인도 구매해놔야겠다.

좋은 웹페이지 즐겨찾기