코드스테이츠_S4U2_2W_월,화

윤뿔소·2022년 11월 21일
0

CodeStates

목록 보기
37/47

브라우저와 브라우저의 동작방식에 대해서 심도 있게 학습하고, 유저에게 다이나믹한 경험을 줄 수 있는 반응형 웹, CSS 애니메이션, Canvas를 배우고 익히자!
기술 면접 단골임! 콜메모리, 브라우저 엔진

브라우저

우리같은 프론트엔드 개발자는 브라우저가 어떻게 동작하고 렌더링되는지 알아야한다! 우리의 코드는 브라우저라는 소프트웨어 프로그램 상에서 수행되기 때문

GUI 기반의 소프트웨어 프로그램.
브라우저는 페이지를 다운로드 하기 위해 응용 계층의 대표적인 프로토콜인 HTTP를 통해 송수신

즉, 웹을 보여주기 위한 프로그램이라 생각하면 된다. 크롬, 사파리, IE&엣지, 파폭 등이 있다.

동작 원리

네트워크 배웠던거 복습시간이다!

  1. 선택한 자원(Resource)를 서버에 요청(Request)
  2. 서버의 응답(Response)
  3. 응답을 가져와 브라우저에 띄움(Rendering)

자세하게 얘기하자면

  1. URL 주소 입력 - DNS 서버에서 검색 및 IP 변환
  2. 받은 IP를 HTTP 프로토콜을 사용해 HTTP 요청 메세지를 생성
  3. TCP 프로토콜을 사용해 해당 IP에 메세지 전송, HTTP 프로토콜을 통해 웹 페이지 URL 정보로 변환
  4. 웹 서버는 변환된 정보에 해당하는 데이터를 탐색하고 2, 3번의 과정을 거쳐 응답 메세지를 사용자의 컴퓨터로 전송
  5. 메세지는 HTTP 프로토콜을 사용해 데이터로 변환, 브라우저에 출력된다!

구조

  • UI(User Interface): 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등에 관련된 GUI 부분을 통칭
  • 브라우저 엔진(Browser Engine): 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어, 문서 객체 모델(DOM) 자료 구조를 구현
    • 블링크(Blink): 웹킷(Webkit)에서 파생된 브라우저 엔진. 크롬, 오페라 등
    • 웹킷(Webkit): KHTML에서 파생된 브라우저 엔진. 사파리 등
    • 트라이던트(Trident): 마이크로소프트의 브라우저 엔진. IE, 엣지가 쓰는 엣지HTML이 파생
  • 렌더링 엔진(Rendering Engine): HTML, CSS 파일을 파싱해 출력, 문서와 이미지를 표시, 브라우저 엔진과 밀접하게 결합
  • 통신(Networking): HTTP 프로토콜, TCP 등. 보통 플랫폼의 독립적인 인터페이스
  • 자바스크립트 해석기(JavaScript Interpreter): JS를 파싱하는 JS 엔진
    • V8: 구글이 개발한 오픈 소스 엔진으로 구글 크롬의 Javascript 엔진
    • JavascriptCore: 애플에서 개발, 처음에 WebKit 프레임워크를 위해 개발되었지만 현재는 사파리와 React Native App를 지원
    • Chakra: 마이크로소프트가 개발한 엔진, Edge 브라우저를 지원
  • UI 백엔드: 렌더링 엔진이 분석한 Render Tree를 브라우저에 그리는 역할을 담당
  • 자료저장소: 쿠키대안인 웹 저장소(Web Storage), 영구저장소인 로컬스토리지와 임시저장소인 세션스토리지로 나뉨, 응용 환경에 맞는 선택이 가능

V8

우리는 크롬을 많이 쓰기에 알아둬야하는 부분이다.

V8 엔진의 메모리 구조는 크게 Heap Memory와 Call Stack으로 구성

힙 메모리(Heap Memory)

힙(heap)은 동적 메모리 할당에 사용되는 자료구조, 여기에 저장되는 메모리는 V8 엔진 내부에서 가장 큰 공간을 차지하고 있으며, 가비지 컬렉션 또한 발생하는 곳

콜 스택(Call Stack)

  • JS는 싱글 스레드 언어임
  • 즉, 콜 스택이 하나라는 의미고 한번에 한 작업만 가능! 콜 스택은 프로그램 상에서 우리가 어디에 있는지 기록하는 자료구조
  • 작동원리
    • 스택이 후입선출(LIFO)이라는 구조를 가지고 있기 때문에 만약 함수를 실행한다면, 해당 함수는 콜 스택의 가장 상단에 위치, 실행 후 바로 제거
      1. 아래 함수부터 호출, 콜스택에 push됨
      2. 스택 내부에서 차례대로 제거, printSquare(), square 함수, multiply 함수까지 성공적으로 실행
      3. 함수 내부 console.log도 같은 과정으로 콜스택에 쌓임
  • 스택 추적(Stack trace): 에러의 결과가 무엇인지 아는 데에 매우 도움

웹 스토리지(Web Storage) 특징

쿠키 자체의 보안상 취약과 더불어 저장소의 절대적인 허용 용량의 적음으로 다른 대안을 찾게 되었고, 이윽고 웹 스토리지(Web Storage)가 출시

  • 웹 브라우저가 직접 데이터를 저장
  • 사용자 측에서 좀 더 많은 양의 정보를 안전하게 저장
  • 저장된 데이터가 클라이언트에만 존재하기에 네트워크 트래픽 비용 또한 줄여줌
  • 오리진(origin)마다 단 하나씩만 존재
    • 오리진(origin): 도메인(domain)과 프로토콜(protocol) 한 쌍으로 이루어진 식별자로, 하나의 오리진에 속하는 모든 웹 페이지는 같은 데이터를 저장하기 때문에 같은 데이터에 접근 가능
  • 종류
    • 로컬스토리지(localStorage): 로컬스토리지 객체는 보관 기한이 없는 데이터.
      • 탭 닫거나 PC 종료해도 사라지지않음.
      • localStorage라는 컬렉션을 통해 저장과 조회가 가능.
      • 도메인마다 별도의 로컬이 생성돼 도메인같다면 전역에서 데이터 공유
    • 세션스토리지(sessionStorage): 세션스토리지 객체는 하나의 세션만을 위한 데이터를 저장.
      • 브라우저 컨텍스트(브라우저가 문서를 표시하는 환경) 내에서만 데이터가 유지로 브라우저 탭, 창을 닫으면 사라짐.
      • sessionStorage라는 컬렉션을 통해 이루어지며, 도메인 별로 별도로 생성
      • 브라우저 컨텍스트가 다르면 서로 다른 영역이 된다는 특징, 같은 페이지 여러개를 열었어도 공유 X
  • 예시
    • 블로그 글을 작성하다가 사용자가 창을 벗어난 경우 관련 작성 내용을 복구하거나 백업해주는 기능
    • 사용자가 입력 form을 통해 정보를 입력하다 페이지에서 벗어난 경우 복구 및 백업해주는 기능
    • 현재 읽은 글의 히스토리 저장(카운팅, 혹은 읽은 글 표시 등으로 활용)

렌더링

HTML, CSS, JavaScript 등 개발자가 작성한 문서가 브라우저에서 출력되는 과정

용어

파싱(Parsing)

프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(syntax analysis)을 하는 단계, 일종의 인터프리터나 컴파일러 구성 요소 가운데 하나
파서가 파싱하여 한 HTML 파일에서 DOM 트리, CSSOM 트리, Render 트리가 나올 수 있음

  • 문서 파싱(document parsing): 브라우저가 코드를 이해하고 사용할 수 있는 구조로 변환하는 걸 의미!
    • 웹 렌더링에선 DOM 트리를 구축하고 및 CSS 파일로 CSSOM 트리를 만드는 것을 파싱한다고 표현
  • 파싱과정: HTML, CSS
    1. 브라우저는 HTML 문서를 받아들자마자 DOM 트리로 파싱
    2. 이때 시작 태그와 마침 태그가 포함되고, 속성 이름과 값도 포함되는 HTML 토큰이 만들어짐
    3. 이런 토큰으로 변한 입력 값은 파서에 의해 노드가 되고, 최종적으로 트리 구조의 DOM으로 구성
    4. HTML 파싱하며 CSS를 만날 경우 텍스트를 CSS 스타일링 레이아웃과 페인팅에 사용하는 데이터 구조인 CSSOM 트리로 파싱
    5. 태그를 만날 경우 렌더링을 차단하면서 HTML 파싱 또한 중단
  • DOM Tree: HTML문서의 요소들의 중첩 관계를 기반으로 노드들이 트리 구조로 중첩, 브라우저는 JS만 알아듣기에 텍스트만 이루어진 HTML을 DOM 트리로 바꿔 이해하게 만듦
  • CSSOM Tree(CSS Object Model): 파싱하던 브라우저는 <link>, <style> 태그를 만나게 되면 파싱을 잠시 멈추고 해당 리소스 파일을 서버로 요청, CSS 코드를 파싱하여 CSSOM 트리를 구축. 완료 후 멈췄던 파싱 구간으로 돌아감.
    특징: CSS는 부모의 속성을 자식이 상속 받아 속성이 중첩됨
  • 렌더 트리(Render Tree): 리소스도 다른 독립적인 트리인 DOM 트리와 CSSOM 트리를 합쳐 렌더링 되게 만드는 트리, 렌더링이므로 사용자에게 보여지지 않는 부분은 제외

레이아웃

여기선 웹 레이아웃 짜기 이런 개념과 다른 부분임

렌더트리를 기반으로 HTML 요소의 레이아웃(위치, 크기 등)을 계산하여 브라우저 화면 어디에 배치할 지 결정하는 과정

아직까지 렌더 트리는 텍스트로 구성된 객체로만 보여 페인팅이라는 작업을 거쳐야지 브라우저 위의 화면으로 그려지게 됨

페인팅

레이아웃에서 결정된 대로 그림을 그리기 시작하는, 이런 픽셀에 대한 정보들을 바탕으로 픽셀을 채워나가는 과정

과정

  1. 사용자가 브라우저를 통해 웹 사이트에 접속합니다.
  2. 브라우저는 서버로부터 HTML, CSS, JavaScript와 같은 웹사이트에 필요한 리소스를 다운 받습니다.
  3. 렌더링 엔진은 전달받은 HTML 문서를 파싱(parsing)해 DOM(Document Object Model, 문서 객체 모델) 트리를 만듭니다.
  4. 이어서 다운 받은 외부 CSS 파일과 함께 포함된 스타일 요소를 파싱(parsing)해 CSSOM(CSS Object Model, CSS 객체 모델) 트리를 만듭니다.
  5. 만든 DOM 트리와 CSSOM 트리를 결합해 Render 트리를 구축합니다.
  6. 레이아웃 과정을 통해 각 요소를 어디에 배치할 지 결정합니다.
  7. 레이아웃 과정이 끝나면 UI 백엔드에서 Render 트리를 화면에 그리기 시작합니다. 이 과정을 paint라고 합니다.

결론

단순히 주소창에 주소를 검색해서 웹 사이트를 모니터를 통해 눈으로 확인할 뿐이지만, 그 내부에서 브라우저가 어떤 과정을 통해 웹 사이트를 띄우는지 살펴보면 굉장히 복잡한 과정이 빠르게 수행되고 있다는 것을 알 수 있게 됐다.
프론트엔드 엔지니어로서 브라우저 렌더링 과정을 알아둔다면 렌더링 최적화 시 어떤 단계에서 최적화를 시켜야 할 지 알 수 있게 된다.

최적화

위에서 봤던 것처럼 과정이 복잡하고 많다. 하지만 웹 앱으로 가는 추세 속에서 사용자가 요소들과 상호작용하며 CRUD 행위를 하는데 만약 최적화가 안돼있다면?
거기에 사용자의 눈에 일련의 과정이 부드럽게 처리 되려면 초당 60 프레임은 반드시 유지해야만 하는데?
리플로우, 리페인트가 일어나고 최적화가 안돼있기에 프레임드랍이 일어나 UX가 떨어진다!

그렇다면 최적화를 꼭 시켜야겠지?

  1. 불필요한 레이아웃을 줄이자
    • 레이아웃 과정에서 불필요하게 계산해야 할 것이 많아지면 엔진도 결국 컴퓨팅 파워에 기대기 때문에 과부하가 불가피하게 생김
    • 그때마다 변경이 되어 렌더 트리를 만들고, 레이아웃을 발생시키고, 페인트를 하는 과정이 연속적으로 발생
    • 레이아웃을 발생시키는(리플로우) 속성들을 지양하자
  2. CSS에서 레이아웃, 페인트를 발생시키는 속성들
    • 리플로우
      • 리플로우 시 리페인트는 필연적으로 일어나므로 가능하다면 리플로우가 발생하는 속성보다 리페인트만 발생하는 속성을 사용
      • 프론트엔드 개발자가 되어 브라우저 렌더링의 최적화 과정을 수행하고자 한다면 레이아웃이 일어나는 상황을 최대한 피하는 것이 좋기 때문에 해당 속성을 알아두는 것이 굉장히 중요
      • 결론: 대개 위치, 혹은 너비와 관련된 속성이 많음, 특히 position 속 left, top 등의 속성이 많을 수록 프레임 유지가 힘듦
      • ⭐️그래서 transform이라는 속성을 사용해 translate를 사용하면 좌표 값을 사용해 위치를 이동, 리페인트만 실행됨!
    • 리페인트
      • 리페인트까진 괜찮!
      • ⭐️팁: opacity라는 속성은 리페인트가 일어나지 않게 해주는 속성이다. visibility/display 보다 opacitiy를 사용하는 것이 성능 개선에 도움된다!
  3. 영향을 주는 노드를 줄이자!
    • 위에서 봤던 것처럼 position은 리플로우가 발생한다. position을 absolute 또는 fixed를 사용해주면 영향을 받는 주변 노드가 감소된다!
    • fixed와 같이 영향을 받는 노드가 전혀 없는 경우 리플로우 과정이 필요 없기 때문에 리페인트 연산 비용만 들여 좋다!

기술 면접에서도 자주 물어보는 내용이기 때문에 꼭 숙지

반응형 웹

현대에 들어서고 JSON이 나오며 동적 스킬이 대두되고, 구글 지도를 거치며 웹 앱에 대한 길이 열리며 상호작용의 중요도 증가 + 각각 다른 비율의 디스플레이를 가진 기기들이 출시되며 여러가지 버전의 웹페이지를 가지는, 다양성을 보이는 웹이 UX 측면에서 큰 반응을 얻는다. 그래서 프엔 개발자라면 필수 스킬이므로 배워두자

브라우저의 크기(스크린의 크기, 디바이스의 종류)에 실시간으로 반응하여 크기에 따라 레이아웃이 변하는 웹 사이트

모바일 퍼스트

반응형 웹하면 바로 떠오르는 전략이다.

Luke Wroblewski가 고안한 전략이자 철학으로 사용자 경험(UX)을 디자인할 때 모바일일 경우에 최우선으로 초점을 맞춰 디자인하는 것

데스크탑 유저보다 모바일 유저가 공유하는 정보가 많고, 늘리는 쪽이 개발하기 편해서이다! 그렇다고 모바일 웹을 늘려놓은 형태는 데탑 UX를 해치겠죠?

특징

  • 반응형 웹은 위의 예시처럼 하나의 URL을 기반으로 화면이 바뀜
    • 네이버처럼 도메인 앞에 m.naver.com은 반응형 웹이 아님!
  • 장점
    • 효율적인 유지보수: 하나의 콘텐츠에 오직 하나의 HTML 소스만 있기 때문에 하나의 소스를 수정하면 모든 스크린 사이즈에 맞춰 컨텐츠가 최적화, 동일하게 반영돼서 편함
    • 검색엔진(SEO) 최적화 유리: 하나의 URL로 모바일, PC를 관리하니까 검색 포털 등 광고를 통한 사용자 접속을 효율적으로 관리
  • 단점
    • 사이트의 속도 저하: 무거움, 실제로 사용하지 않은 자원을 전송 받거나 실제 사용되는 이미지보다 더 큰 이미지를 사용해 로딩의 속도나 이미지 리사이징의 문제로 성능 저하
    • 웹브라우저 호환성 문제: 크로스 브라우징 중 하나의 리소스를 바탕으로 여러개를 렌더링하다보니 디자인이 깨지는 경우가 발생(예: CSS3는 IE 8 버전 사용 불가)

미디어 쿼리

구체적인 조건으로 필요한 스타일을 적용
뷰포트(브라우저 창)의 크기에 따라 서로 다른 조판을 생성할 수 있기 때문에 많이 씀

적용법

미디어 속성 내 해당 조건을 만족할 때에만 해당 스타일을 적용

기본 구조

  • 미디어 타입: 코드가 어떤 미디어를 위한 것인지 브라우저에 알려줌
    • all: 모든 미디어 타입
    • print: 프린터
    • screen: 컴퓨터 화면
    • speech: 스크린 리더
  • 조건(너비 및 높이): 지정한 창의 너비나 높이를 기준으로 기준이 만족되면 스타일이 적용되고, 만족되지 않으면 적용 X
    • min-widthmax-width, width 등의 미디어 기능을 활용
  • 방향성: 세로 모드인지 가로 모드인지 검사, orientation

HTML

/* 400px~1000px */
<link href="css파일이름.css" media="screen and (min-width: 400px) and (max-width: 1000px)" rel="stylesheet">
<style type="text/css" media="screen and (min-width: 400px) and (max-width: 1000px)">
	/* 여기 css를 작성 */
</style>

CSS

@media 미디어 타입 (조건(너비 및 높이)) {
    (CSS 입력하는 부분)
}

--예제
@media screen (max-width: 400px) {
    body {
			color: red;
		}
}
@media (orientation: landscape) {
    body {
        color: rebeccapurple;
    }
}

연산을 쓰는 미디어 쿼리

논리곱(and), 논리합(or), 부정(not)

/* 논리곱: and를 사용 */
@media screen and (min-width: 400px) and (orientation: landscape) {
    body {
        color: blue;
    }
}
/* 논리합: 콤마로 분리 */
@media screen and (min-width: 600px), screen and (orientation: landscape) {
    body {
        color: blue;
    }
}
/* 부정: not, 방향이 세로인 경우에만 텍스트가 파란색으로 적용 */
@media not all and (orientation: landscape) {
    body {
        color: blue;
    }
}

CSS 심화

CSS 애니메이션을 제대로 주는 법과 HTML 태그의 캔버스에 대해서 알아보자!

@keyframes

CSS 스타일을 부드럽게 커스텀 가능한 키워드이다!
1. 먼저 CSS로 키프레임 블록을 만들어아한다.

/* '%' 단위로 시간 진행에 따른 상태를 작성해주면 됨 */

@keyframes 애니메이션이름 {
	0% {            /* from 이라고 작성해도 됨 */
		CSS속성 : 속성값; 
	}

	50% {           /* 애니메이션 진행도에 따른 스타일을 설정 */
                  /* 필요하다면 1부터 99까지도, 소수점까지도 모두 작성해도 됨*/
		CSS속성 : 속성값;
	}

	100% {          /* to 라고 작성해도 됨*/
		CSS속성 : 속성값;
	}
}
  1. 그리고 애니를 적용시키고 싶은 곳에 animation 속성을 넣어 부여한다.
@keyframes lotate {
	0% {
		transform : rotate(0deg)
	}

	50% {
		transform : rotate(180deg)
	}

	100% {
		transform : rotate(360deg)
	}
}

애니메이션 속성

animation : 띄어쓰기로 쭉 나열하면 아래의 속성들을 한 번에 지정할 수 있음

  • animation-name : 애니메이션의 중간 상태를 지정하는 이름. @keyframes 블록에 작성
    • @keyframes과 연결해주는 장치
  • animation-duration : 한 싸이클의 애니메이션이 재생될 시간 지정
  • animation-delay : 애니메이션의 시작을 지연시킬 시간 지정
  • animation-direction : 애니메이션 재생 방향을 지정
    • normal : 기본 값. 재생이 끝나면 처음부터 다시 재생
    • reverse : 역방향으로 재생
    • `alternate : 순방향부터 역방향을 번갈아가며 재생
    • alternate-reverse : 역방향부터 순방향을 번갈아가며 재생
  • animation-iteration-count : 애니메이션이 몇 번 반복될지 지정
  • animation-play-state : 애니메이션을 재생 상태. 멈추거나 다시 재생 시킬 수 있음
  • animation-timing-function : 중간 상태들의 전환을 어떤 시간간격으로 진행할지 지정
  • animation-fill-mode : 애니메이션이 재생 전 후의 상태 지정
    • none : 기본 값. 재생중이 아닌 경우 요소의 스타일을 유지
    • forwards : 재생중이 아닌 경우 마지막 키프레임 스타일을 유지
    • backwards : 재생중이 아닌 경우 첫 번째 키프레임 스타일을 유지
    • both : 재생 전에는 첫 번째 키프레임 스타일을, 재생 후에는 마지막 키프레임 스타일을 유지

합치기

@keyframes와 애니메이션 속성을 합쳐보자!

#logo {
	**animation-name : lotate;**    /* lotate 라는 이름의 키프레임 애니메이션을 */
	animation-duration : 3s;               /* 3초 동안 재생하며, */
	animation-iteration-count : infinite;  /* 애니메이션을 무한 반복하고, */
    animation-timing-function : linear;    /* 선형으로 재생 */
}

/* 아래와 같이 일괄 작성해도 동일하게 적용 */
#logo {
	animation : **lotate** 3s infinite linear;
}


이처럼 중간값을 지정해 다양한 애니메이션을 줄 수 있다!

실습

<div class="blueBall"></div>
<div class="redBall"></div>
이 두개의 div 가지고 만들어보았다.

@keyframes blueBall {
  0% {
    top: 0px;
    background-color: #fff;
  }
  95% {
    width: 100px;
    background-color: cornflowerblue;
  }
  to {
    top: 300px;
    width: 115px;
    height: 90px;
    transform: translate(100px, 100px);
    background-color: rgb(56, 94, 165);
  }
}
@keyframes redBall {
  0% {
    left: 0px;
    background-color: #fff;
  }
  90% {
    width: 100px;
    background-color: #e84545;
  }
  to {
    left: 300px;
    width: 100px;
    height: 100px;
    transform: translate(100px, 100px);
    background-color: red;
  }
}

div.blueBall {
  position: relative;
  left: 100px;
  top: 0;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: blue;
  animation: blueBall 1s ease-in Infinite Alternate;
}

div.redBall {
  position: relative;
  left: 100px;
  top: 0;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: red;
  animation: redBall 1.5s ease-out Infinite Alternate;
}

이런 식으로 만들 수 있다!

Canvas

HTML의 <canvas> 태그 + JS(DOM) = 다양한 그래픽 요소

<canvas id="canvas">
	캔버스를 지원하지 않는 브라우저에서는 캔버스 대신 태그 사이 내용이 표시됩니다.
</canvas>

이제 자바스크립트를 사용해서 엘리먼트를 선택

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

캔버스는 canvas 엘리먼트를 DOM으로 조작하는 방식으로 작성된다. 따라서 엘리먼트를 선택할 때 사용할 id를 작성해야한다!

준비

너비와 높이를 설정해야한다! HTML과 JS 각각 써줄 수 있으며 각자 특징이 있다.

HTML

이 방법에 width, height 속성은 어떤 단위로 속성값을 설정해주든 픽셀로만 인식

<canvas id="canvas" width="500" height="500"></canvas>
		// 500픽셀 * 500픽셀로 설정됩니다.

<canvas id="canvas" width="50vw" height="40vh"></canvas>
		// vw, vh를 전달했지만 50픽셀 * 40픽셀로 설정됩니다.

JS

유동적인 값도 설정해줄 수 있기 때문에 캔버스의 크기가 고정되어있지 않은 경우에 사용

canvas.width = 50vw;
canvas.height = 40vh;
// DOM으로 설정하면 50vw * 40vh 로 단위값을 지정해도 설정 가능

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 화면 크기에 맞춰서 설정 가능

실습

클릭하면 사각형이 나오는 식으로 해보겠다!

캔버스로 사각형 그리기

  • 색칠된 사각형 그리기
    1. fillStyle 속성으로 사각형 내부를 색칠할 색상을 설정
    2. fillRect 메소드를 사용해 사각형을 그려줌
ctx.fillStyle = 'blue'
ctx.fillRext = (10, 10, 100, 50)
//전달 인자는 순서대로 x좌표, y좌표, 가로길이, 세로길이
  • 선으로만 그리기
    1. lineWidth 속성으로 선의 굵기를, strokeStyle 속성으로 선의 색상을 설정해줍니다.
    2. strokeRect 메소드를 사용해 사각형을 그려줍니다.
ctx.lineWidth = 5;
ctx.strokeStyle = "black";
ctx.strokeRect(10, 10, 100, 50)
// 전달 인자는 이번에도 순서대로 x좌표, y좌표, 가로길이, 세로길이
// 위에서 그려준 색칠된 사각형 바로 위에 그려보기
  • 사각형으로 지우기: clearRect 메소드로 지울 범위를 설정
ctx.clearRect( 20, 20, 80, 30)
// 전달 인자는 역시 동일하다. 그려놓은 사각형 가운데 부분을 지워보세요.

클릭 이벤트 만들기

클릭이벤트가 일어날 때의 마우스의 위치 구하고 거기에 사각형이 생기는 코드 넣어주기

  • 화면에서의 마우스 위치에서 화면에서의 캔버스 위치를 빼기
    • 화면상 마우스 위치를 구하는 이벤트 객체의 속성
      X좌표 : event.clientX
      Y좌표 : event.clientY
    • 화면상 캔버스의 위치를 구하는 속성
      X좌표 : ctx.canvas.offsetLeft
      Y좌표 : ctx.canvas.offsetTop
  • 혹은 event.offsetX , event.offsetY 로 바로 구할 수도 있음!!
canvas.onclick = function (event) {
  const x = event.clientX - ctx.canvas.offsetLeft
  const y = event.clientY - ctx.canvas.offsetTop
  // 구한 좌표를 이용해서 사각형을 그리는 코드를 작성

  ctx.fillRect(x - 15, y - 15, 30, 30);
	// 클릭할 때마다 30픽셀*30픽셀 크기의 사각형을 그리도록 하려고 한다.
	// 이 때, x, y를 그대로 전달하면 해당 좌표부터 사각형이 시작되어 어색한 느낌을 줌
	// 클릭한 위치를 사각형의 정중앙이 되게 하려면 사각형크기/2 한 만큼 좌표에서 빼주면 됨
	// 따라서 x - 15, y - 15 를 전달
}

결과

const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

canvas.onclick = function (event) {
  const x = event.clientX - ctx.canvas.offsetLeft;
  const y = event.clientY - ctx.canvas.offsetTop;

  ctx.fillStyle = "#8EC3B0";
  ctx.fillRect(x - 15, y - 15, 30, 30);
};

참고

캔버스 기반 유용하게 쓸 수 있는 라이브러리 Chart.js가 있다. 그것도 한번 보자

HMTL

CDN 및 너비와 높이를 결정해 차트의 치수를 결정
차트의 너비와 높이의 비율은 캔버스의 너비와 높이에 따라 비례하게 설정

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" ></script>
</head>
<body>
<canvas id="myChart" width="600" height="400"></canvas>
</body>

JS

DOM을 이용해 인스턴스화 후 labeldata를 정의한 뒤, config 객체 안에 넣어 Chart constructor에 전달

  1. myChart 변수를 선언
  2. 할당한 new Chart Contructor의 첫번째 전달인자로 앞서 만든 myCanvas 변수를 전달
  3. 두번째 전달인자인 config 객체에서는 Chart.js가 차트를 그리는데 필요한 모든 정보가 포함
    • type 키를 통해 그리고자 하는 차트의 유형을 지정할 수 있습니다.
      • line, bar, radar, polarArea, pie, doughnut, bubble
    • data 키에는 실제 데이터들을 담고 있음.
    • backgroundColor 키는 막대 별로 색상을 다르게 하기 위해서 사용. 기본값은 rgba(0, 0, 0, 0.1)
let myCanvas = document.getElementById("myChart").getContext("2d");

const labels = [
        'January',
        'February',
        'March',
        'April',
        'May',
        'June',
    ];

    const data = {
        labels: labels,
        datasets: [{
        label: 'My First dataset',
        backgroundColor: 'rgb(255, 99, 132)',
        borderColor: 'rgb(255, 99, 132)',
        data: [0, 10, 5, 2, 20, 30, 45],
        }]
    };

    const config = {
        type: 'line',
        data: data
    };

    // 이 부분이 chart constructor
    const myChart = new Chart(
        myCanvas,
        config
    );

결과

또다른 예시

알게된 것

  • CSS 애니메이션만 메인비쥬얼부터 잘 쓰면 좋다! 스크롤 애니메이션, 클릭 이벤트 등등 오픈 소스로 구글링하면 많다! 잘 써보자
  • 내 코드펜에 구현된 CSS 애니메이션 레퍼런스가 있다. 참고하자!
  • CSS 애니메이션 라이브러리도 진짜 많다! 한번 보자!
profile
코뿔소처럼 저돌적으로

0개의 댓글