WECODE Project 코드 리뷰 #2. 색상 테마

김상웅·2022년 5월 13일
0

[사이드프로젝트]

목록 보기
2/9
post-custom-banner

WECODE Project Javascript code reveiwe #2


자기소개 페이지 중 자바스크립트를 활용하여 동적 기능을 구현한 두번째 부분에 대해 소개하려고 합니다.
전체 소스코드
자기소개 페이지
첫번째 기능 - Slide
세번째 기능 - Light/Dark mode

🚥 Color Theme - button


두번째는 자기소개 페이지의 색상 테마를 바꿀 수 있는 기능입니다.
밋밋할 수 있는 페이지를 다채롭게 바꿔보자 다음 기능을 적용해봤습니다.

📌 Html Layout


controller 클래스를 가진 전체 레이아웃

  • 위 사진의 HTML코드는 다음과 같습니다.

우선 톱니바퀴 모양의 버튼은 icons8의 아이콘을 참조했습니다.
이 톱니바퀴 버튼은 9가지 색상을 담은 <div class="control__colors"> </div>를 보여주고 없애주는 역할을 수행합니다.

실질적으로 색상을 선택하는 <div class="control__colors"> </div>의 자식 요소는 자바스크립트를 활용하여 HTML요소를 추가하였습니다. (자바스크립트 코드를 확인해주세요!)

 <div class="controller">
   <div class="theme-color">
     	<button class="color-btn">
       		<img class="color-controller"
           		src=icons8_톱니바퀴_이미지./>
     	</button>
   		<div id="jsColors" class="control__colors visible">
         <!--
        <div class="controls__color" style="background: ${color} "}> </div>	
         -->
   		</div>
   </div>
 </div>

📌 Css Styling


  • 다음은 css코드입니다.
  • .controller 선택자의 자식요소로는 .theme-color.mode-changer 두개가 있다는 점을 참고해주세요. 후자의 선택자에 대해서는 다음 포스팅에서 알아보겠습니다.

아래 사진은 .controller 선택자만 position: absolute값을 가진 상태의 모습입니다.
주요 정보를 담은 .container역시 body태그를 참조하기 때문에 위치가 왼쪽으로 치우쳐있으며,
색상을 선택하는 .control__colors.controller의 하단에 위치합니다.

position: absoulte 값을 가진 선택자는 position: relative값을 가진 선택자의 위치를 참조합니다.
저는 위 사진 속 요소들을 배치할 때 relative값을 상위 선택자에 설정하지 않았기 때문에 position: relative값은 body 태그를 참조합니다.
(.container의 다른 자식 요소들의 코드를 보시면 relative 값이 추가 된 선택자가 있습니다. 이 선택자의 자식 요소에 absolute 값을 추가하면 body태그가 아닌 부모 요소의 위치를 참조하게 됩니다.)

.controller {
  position: absolute;
  top: 0;
  right: 0;
  margin-top: 10px;
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  width: 300px;
}
.theme-color button {
  border: none;
  outline: none;
  background: inherit;
  padding: 5px;
  cursor: pointer;
}
.theme-color button:hover {
  transform: scale(calc(1.2));
}
.control__colors {
  display: flex;
  position: absolute;
  top: -50px;
  left: -50px;
  background: #d5d5d5;
  padding: 10px;
  border-radius: 5px;
}
.control__colors .controls__color {
  width: 20px;
  height: 20px;
  margin: 0 5px;
  border-radius: 50%;
  cursor: pointer;
  transition: 0.3s ease;
}
.control__colors .controls__color:hover {
  transform: scale(calc(1.3));
}

📌 Javascript code


다음은 자바스크립트 코드입니다.

  • 먼저 이벤트를 추가해야되는 HTML 요소에 접근해줍니다.

Color Theme을 통해 색상을 바꿀 요소는 다음과 같습니다.
1. 각 페이지의 제목 → title
2. 각 페이지를 선택하는 navigation 항목 → navList
3. 주요 정보를 담고 있는 .container 선택자의 테두리 → containerDiv
4. 기술란의 퍼센트를 보여주는 .skill--bar 선택자의 색상 → skillBar
5. Dark/Light모드를 설정할 수 있는 버튼 → sliderBtn
6. side section과 main section을 구분하는 선 → sideSec

이벤트를 추가해야 하는 요소는 다음과 같습니다.
1. 9가지 색상을 담는 요소 → pallete
2. pallete를 나타내고 없애주는 톱니바퀴 버튼 → btn

const title = document.querySelectorAll(".main--title");
const navList = document.querySelectorAll(".nav--list");
const containerDiv = document.querySelector(".container");
const skillBar = document.querySelectorAll(".skill--bar");
const sliderBtn = document.querySelector(".slider.round");
const sideSec = document.querySelector(".side--section");

const pallete = document.querySelector(".control__colors");
const btn = document.querySelector(".color-btn");

  • 다음 9가지 색상을 화면에 보여주기 위해 HTML요소를 추가해줍니다.
  1. COLOR_THEME 배열에 9가지 색상을 담아주었습니다.

  2. palletMaker(color) 함수는 div 요소를 반환하는 함수입니다.
    color라는 파라미터를 받아오는데 위에서 언급했던 COLOR_THEME의 각각의 원소를 받아옵니다.
    반환되는 div 요소들은 pallete의 자식 요소에 생성됩니다.

  3. btnonclick 이벤트를 설정해줍니다.
    pallete의 클래스에 visible이라는 클래스의 여부를 확인해줍니다.
    visible 클래스는 display: none;이라는 값을 가지고 있는데, invisible로 수정해야될 것 같습니다.

btn을 클릭하였을 때 visible 클래스가 포함되어 있다면, 그 클래스를 지우고 내부 HTML에 배열의 내장함수 map을 이용하여 COLOR_THEME의 갯수만큼 div 요소를 자식 요소로 반환하여 줍니다.

btn을 클릭하였을 때 visible 클래스가 포함되어 있지 않다면, 클래스를 추가하여 위의 요소를 숨겨줍니다.

const COLOR_THEME = [
	"#2c2c2c",
	"#e2e2e2",
	"#ff3b30",
	"#ff9500",
	"#ffcc00",
	"#4cd963",
	"#5ac8fa",
	"#0579ff",
	"#5856d6",
];

function palletMaker(color) {
	return `<div class="controls__color" style="background: ${color} "}> </div>`;
}

btn.onclick = () => {
	const classCheck = pallete.classList.contains("visible");

	if (classCheck) {
		pallete.classList.remove("visible");
		pallete.innerHTML = COLOR_THEME.map((item) => palletMaker(item)).join("");
	} else {
		pallete.classList.add("visible");
	}
};

  • 색상을 선택할 수 있는 파레트의 동작을 구현했으니, 이제 색상을 변경해주는 함수를 만들 차례입니다.

자바스크립트 코드 상단에서 접근한 Html 요소들에 대해 style을 바꾸어줍니다.
처음에는 자바스크립트를 통해 추가한 html요소 접근에 애를 먹었습니다.

document.addEventListner("click", callback Function)
(아래의 코드와 동일) 위의 방법은 document의 모든 부분에서 click 이벤트가 발생합니다.
발생한 이벤트 중 e.target.className.controls__color 선택자를 가리키는 요소만 선택되도록 조건문을 작성하였는데요.

1) 문서 전체의 모든 부분을 클릭할 수 있으면서,
2) 선택자가 .controls__color로 조건이 충족되는 경우
→ Html 요소의 style을 바꿀 수 있도록 조건문과 실행 코드를 작성해주었습니다.

동일한 클래스를 가진 요소들은 document.querySelectorAll()을 통해 NodeList로 반환됩니다.
반환된 요소들은 배열의 index 값에 접근할 수 있는 반복문을 통해 style을 제어하는 함수로 구분해주었습니다.

function colorChanger(e) {
	const PAINT = "controls__color";
	const color = e.target.style.backgroundColor;

	if (e.target.className === PAINT) {
		sideSec.style.borderRight = `1px solid ${color}`;
		sliderBtn.style.backgroundColor = color;
		containerDiv.style.boxShadow = `0 3px 10px ${color}, 0 1px 3px ${color}`;
		navListTitleColor(color);
		skillBarColor(color);
	} else {
		console.log("please click the pallet");
	}
}
document.addEventListener("click", colorChanger);

function navListTitleColor(color) {
	for (let i = 0; i < navList.length; i++) {
		navList[i].style.color = color;
      // title과 navList의 length가 동일하여 같은 반복문에 작성
		title[i].style.color = color;
	}
}

function skillBarColor(color) {
	for (let i = 0; i < skillBar.length; i++) {
		skillBar[i].style.backgroundColor = color;
	}
}


🛠️ 보완해야할 점

1. css 선택자 중 .visible 클래스 이름 바꾸어주기 (2022-05-16부 완료)
2. javascript 중 document.addEventLisnter 대신 palletMaker() 함수 실행 이후에 DOM 접근 해보기

palleteMaker()함수가 실행된 조건문 내부에서 접근이 가능한 것을 알았습니다.

	const paint = document.querySelector(".controls__color");
    console.log(paint);

콘솔창의 결과는 아래와 같이 동적으로 추가된 요소에 접근이 가능했습니다.

하지만 조건문 내부에 다시 조건문을 적게 되고, 다시 onclick함수를 반복해서 적어야했습니다.
좀 더 공부를 해본 다음 더 효울적인 방법으로 접근을 해야될 것 같습니다😂

profile
누구나 이해할 수 있도록
post-custom-banner

0개의 댓글