38가지 자바스크립트&리액트 튜토리얼
웹서핑을 하다가 초보자를 위한 40가지의 자바스크립트 프로젝트라는 걸 보게 됐다. 딱히 할 것도 없으니 이거나 한번 리스트만 보고 쭉 해봐야겠다. 근데 바닐라 자바스크립트 쪽은 27개밖에 없
frontend-bear.tistory.com
최종 결과물
Color Flipper
#f15025
HTML
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>38JS - Color_flipper</title>
<script src="./color_flipper.js"></script>
<link rel="stylesheet" href="./reset.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<script>
const colorFlipper = new ColorFlipper('.container');
</script>
</body>
</html>
CSS
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 200px;
height: 300px;
padding: 20px 40px;
transition: 0.3s ease-in-out;
}
.color_title {
font-size: 20px;
font-weight: 700;
margin-bottom: 20px;
}
.color_value {
font-size: 14px;
margin-bottom: 20px;
}
.color_btn {
border: 1px solid #fff;
padding: 5px 15px;
background: transparent;
color: #fff;
}
JS
constructor()
target
인자를 받아서 document에서 탐색해 this.target으로 저장- (Option)
colorCode
변수를 할당해 this.target 내부의 color_value 클래스의 DOM을 할당 - (Option)
actionButton
변수를 할당해 this.target 내부의 color_btn 클래스의 DOM을 할당 init()
매서드 실행
init()
- this.actionButton에 클릭 이벤트 리스너를 할당, 실행하는 함수는
this.changeColor
- 초기에 색이 한번 변경되야 하므로
this.changeColor();
실행
changeColor()
- r,g,b 변수를 각각 지정해
Math.random() * 256
으로 0부터 255 사이의 숫자를 생성 - 위에서 생성된 변수들을 가지고
this.checkBackgroundColor(r,g,b)
매서드 실행 randomColor
변수를 할당 후rgb(${r}, ${g}, ${b})
의 문자열 형태로 저장this.target
의 backgroundColor를 randomColor로 변경- this.colorCode의 text를
[ ${randomColor} ]
로 변경
checkBackgroundColor(r,g,b) - Option
- 입력받은 rgb값이 각각 155를 초과할 경우(밝은 색일 경우) 텍스트와 버튼의 컬러를 #000으로 변경
- 그 외의 경우 #fff로 변경
class ColorFlipper {
constructor(target) {
this.target = document.querySelector(target);
this.colorCode = this.target.querySelector(".color_value");
this.actionButton = this.target.querySelector(".color_btn");
this.init();
}
init() {
this.actionButton.addEventListener("click", this.changeColor.bind(this));
this.changeColor();
}
changeColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
this.checkBackgroundColor(r, g, b)
const randomColor = `rgb(${r}, ${g}, ${b})`;
this.target.style.backgroundColor = randomColor;
this.colorCode.textContent = `[ ${randomColor} ]`
}
checkBackgroundColor(r, g, b) {
if (r > 155 && g > 155 && b > 155) {
this.colorCode.style.color = "#000";
this.actionButton.style.color = "#000";
this.actionButton.style.borderColor = "#000";
this.target.querySelector("h1").style.color = "#000";
}else{
this.colorCode.style.color = "#fff";
this.actionButton.style.color = "#fff";
this.actionButton.style.borderColor = "#fff";
this.target.querySelector("h1").style.color = "#fff";
}
}
}
ColorFlipper
객체를 만들어서 target으로 해당 container의 클래스명을 받고,
해당 container 내부의 DOM인 color_value
와 color_btn
를 각각 colorCode와 actionButton로 연결해 주었다.
init에서 actionButton
에 이벤트 리스너로 changeColor
를 걸어주었고,
this를 이용해야 해서 bind 시켜주었다.
그리고 r, g, b 변수를 만들어서 0부터 255까지 랜덤으로 선택 되게 한 후,randomColor
변수를 만든 뒤,
this.target의 background 컬러를 변경해 주고,
this.colorCode의 textContent를 변경해 주었다.
checkBackgroundColor()
메서드로 rgb 값이 각각 155 이하일 때는 텍스트가 검은색으로,
초과일 때는 하얀색으로 바뀌게 작성 후 rgb 값 계산 후 실행되게 해 주었다.
init()
내부에서 changeColor()
를 한번 실행해 주어 초기에 랜덤으로 값이 바뀌게 설정하였다.
응용 사례
여러개의 container를 만들고 한번에 여러요소의 색을 바꾸기
하기와 같은 형태로 여러개의 colorBlock을 바꿔보자.
Color Flipper
#f15025Color Flipper
#f15025Color Flipper
#f15025 <div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
ColorFlipper의 constructor내부의 this.target을 아래와 같이 수정해준다.
(클래스명이 아닌 직접 DOM을 받을 수 있게 수정)
class ColorFlipper {
constructor(target) {
this.target = target;
...
이후 html 하단의 const colorFlipper = new ColorFlipper('.container'); 부분을 아래와 같이 바꿔준다.
const colorBlocks = document.querySelectorAll('.container');
const colorFlipperInit = () => {
colorBlocks.forEach((colorBlock) => {
const colorFlipper = new ColorFlipper(colorBlock);
});
}
colorFlipperInit();
이러면 각각의 요소들이 개별적으로 동작하고, 따로 버튼을 만들어 onclick 속성으로 colorFlipperInit()을 실행시켜주면
모든 요소의 색이 변하게 된다.
JS 리팩토링
주요 변경 사항
- changeColor() 메서드를 세부 기능에 따라 여러 개의 메서드로 분리
- generateRandomColor() 메서드를 추가하여 임의의 색상을 생성
- setRandomColor() 메서드를 추가하여 타겟 요소의 배경색과 색상 코드를 설정
- updateTextColor() 메서드를 추가하여 텍스트 색상 업데이트
- isLightColor() 메서드를 추가하여 주어진 색상이 밝은 색상인지 확인하는 로직을 개선
class ColorFlipper {
constructor(target) {
this.target = document.querySelector(target);
this.colorCode = this.target.querySelector(".color_value");
this.actionButton = this.target.querySelector(".color_btn");
this.init();
}
init() {
this.actionButton.addEventListener("click", this.changeColor.bind(this));
this.changeColor();
}
changeColor() {
const randomColor = this.generateRandomColor();
this.setRandomColor(randomColor);
this.updateTextColor(randomColor);
}
generateRandomColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
setRandomColor(color) {
this.target.style.backgroundColor = color;
this.colorCode.textContent = `[ ${color} ]`;
}
updateTextColor(color) {
const isLightColor = this.isLightColor(color);
const textColor = isLightColor ? "#000" : "#fff";
this.colorCode.style.color = textColor;
this.actionButton.style.color = textColor;
this.actionButton.style.borderColor = textColor;
this.target.querySelector("h1").style.color = textColor;
}
isLightColor(color) {
const [r, g, b] = color
.substring(color.indexOf("(") + 1, color.lastIndexOf(")"))
.split(",")
.map(Number);
return r > 155 && g > 155 && b > 155;
}
}
38가지 자바스크립트&리액트 튜토리얼
웹서핑을 하다가 초보자를 위한 40가지의 자바스크립트 프로젝트라는 걸 보게 됐다. 딱히 할 것도 없으니 이거나 한번 리스트만 보고 쭉 해봐야겠다. 근데 바닐라 자바스크립트 쪽은 27개밖에 없
frontend-bear.tistory.com
최종 결과물
Color Flipper
[ rgb(173, 184, 104) ]
HTML
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>38JS - Color_flipper</title>
<script src="./color_flipper.js"></script>
<link rel="stylesheet" href="./reset.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<script>
const colorFlipper = new ColorFlipper('.container');
</script>
</body>
</html>
CSS
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 200px;
height: 300px;
padding: 20px 40px;
transition: 0.3s ease-in-out;
}
.color_title {
font-size: 20px;
font-weight: 700;
margin-bottom: 20px;
}
.color_value {
font-size: 14px;
margin-bottom: 20px;
}
.color_btn {
border: 1px solid #fff;
padding: 5px 15px;
background: transparent;
color: #fff;
}
JS
constructor()
target
인자를 받아서 document에서 탐색해 this.target으로 저장- (Option)
colorCode
변수를 할당해 this.target 내부의 color_value 클래스의 DOM을 할당 - (Option)
actionButton
변수를 할당해 this.target 내부의 color_btn 클래스의 DOM을 할당 init()
매서드 실행
init()
- this.actionButton에 클릭 이벤트 리스너를 할당, 실행하는 함수는
this.changeColor
- 초기에 색이 한번 변경되야 하므로
this.changeColor();
실행
changeColor()
- r,g,b 변수를 각각 지정해
Math.random() * 256
으로 0부터 255 사이의 숫자를 생성 - 위에서 생성된 변수들을 가지고
this.checkBackgroundColor(r,g,b)
매서드 실행 randomColor
변수를 할당 후rgb(${r}, ${g}, ${b})
의 문자열 형태로 저장this.target
의 backgroundColor를 randomColor로 변경- this.colorCode의 text를
[ ${randomColor} ]
로 변경
checkBackgroundColor(r,g,b) - Option
- 입력받은 rgb값이 각각 155를 초과할 경우(밝은 색일 경우) 텍스트와 버튼의 컬러를 #000으로 변경
- 그 외의 경우 #fff로 변경
class ColorFlipper {
constructor(target) {
this.target = document.querySelector(target);
this.colorCode = this.target.querySelector(".color_value");
this.actionButton = this.target.querySelector(".color_btn");
this.init();
}
init() {
this.actionButton.addEventListener("click", this.changeColor.bind(this));
this.changeColor();
}
changeColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
this.checkBackgroundColor(r, g, b)
const randomColor = `rgb(${r}, ${g}, ${b})`;
this.target.style.backgroundColor = randomColor;
this.colorCode.textContent = `[ ${randomColor} ]`
}
checkBackgroundColor(r, g, b) {
if (r > 155 && g > 155 && b > 155) {
this.colorCode.style.color = "#000";
this.actionButton.style.color = "#000";
this.actionButton.style.borderColor = "#000";
this.target.querySelector("h1").style.color = "#000";
}else{
this.colorCode.style.color = "#fff";
this.actionButton.style.color = "#fff";
this.actionButton.style.borderColor = "#fff";
this.target.querySelector("h1").style.color = "#fff";
}
}
}
ColorFlipper
객체를 만들어서 target으로 해당 container의 클래스명을 받고,
해당 container 내부의 DOM인 color_value
와 color_btn
를 각각 colorCode와 actionButton로 연결해 주었다.
init에서 actionButton
에 이벤트 리스너로 changeColor
를 걸어주었고,
this를 이용해야 해서 bind 시켜주었다.
그리고 r, g, b 변수를 만들어서 0부터 255까지 랜덤으로 선택 되게 한 후,randomColor
변수를 만든 뒤,
this.target의 background 컬러를 변경해 주고,
this.colorCode의 textContent를 변경해 주었다.
checkBackgroundColor()
메서드로 rgb 값이 각각 155 이하일 때는 텍스트가 검은색으로,
초과일 때는 하얀색으로 바뀌게 작성 후 rgb 값 계산 후 실행되게 해 주었다.
init()
내부에서 changeColor()
를 한번 실행해 주어 초기에 랜덤으로 값이 바뀌게 설정하였다.
응용 사례
여러개의 container를 만들고 한번에 여러요소의 색을 바꾸기
하기와 같은 형태로 여러개의 colorBlock을 바꿔보자.
Color Flipper
[ rgb(115, 174, 253) ]Color Flipper
[ rgb(66, 54, 206) ]Color Flipper
[ rgb(57, 164, 4) ] <div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
<div class="container">
<h1 class="color_title">Color Flipper</h1>
<span class="color_value">#f15025</span>
<button class="color_btn">click me</button>
</div>
ColorFlipper의 constructor내부의 this.target을 아래와 같이 수정해준다.
(클래스명이 아닌 직접 DOM을 받을 수 있게 수정)
class ColorFlipper {
constructor(target) {
this.target = target;
...
이후 html 하단의 const colorFlipper = new ColorFlipper('.container'); 부분을 아래와 같이 바꿔준다.
const colorBlocks = document.querySelectorAll('.container');
const colorFlipperInit = () => {
colorBlocks.forEach((colorBlock) => {
const colorFlipper = new ColorFlipper(colorBlock);
});
}
colorFlipperInit();
이러면 각각의 요소들이 개별적으로 동작하고, 따로 버튼을 만들어 onclick 속성으로 colorFlipperInit()을 실행시켜주면
모든 요소의 색이 변하게 된다.
JS 리팩토링
주요 변경 사항
- changeColor() 메서드를 세부 기능에 따라 여러 개의 메서드로 분리
- generateRandomColor() 메서드를 추가하여 임의의 색상을 생성
- setRandomColor() 메서드를 추가하여 타겟 요소의 배경색과 색상 코드를 설정
- updateTextColor() 메서드를 추가하여 텍스트 색상 업데이트
- isLightColor() 메서드를 추가하여 주어진 색상이 밝은 색상인지 확인하는 로직을 개선
class ColorFlipper {
constructor(target) {
this.target = document.querySelector(target);
this.colorCode = this.target.querySelector(".color_value");
this.actionButton = this.target.querySelector(".color_btn");
this.init();
}
init() {
this.actionButton.addEventListener("click", this.changeColor.bind(this));
this.changeColor();
}
changeColor() {
const randomColor = this.generateRandomColor();
this.setRandomColor(randomColor);
this.updateTextColor(randomColor);
}
generateRandomColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
setRandomColor(color) {
this.target.style.backgroundColor = color;
this.colorCode.textContent = `[ ${color} ]`;
}
updateTextColor(color) {
const isLightColor = this.isLightColor(color);
const textColor = isLightColor ? "#000" : "#fff";
this.colorCode.style.color = textColor;
this.actionButton.style.color = textColor;
this.actionButton.style.borderColor = textColor;
this.target.querySelector("h1").style.color = textColor;
}
isLightColor(color) {
const [r, g, b] = color
.substring(color.indexOf("(") + 1, color.lastIndexOf(")"))
.split(",")
.map(Number);
return r > 155 && g > 155 && b > 155;
}
}