⭐️⭐️⭐️ 별점 star-rating을 구현해 보자
요즘 배달, 쇼핑몰, 어플, 장소 등 어느 곳에서나 별점을 볼 수 있을 것이다.
해당 상품의 별점을 통해 만족도를 확인하기 때문에! 정말 기본이 되는 기능 중 하나인 별점을 구현해보고자 한다.
✨ 결과물
👉🏻 star-rating은 재사용이 가능하도록 코드를 구현하였으며, 마우스 반응에 따라 효과를 다르게 주었다.
💛 star를 클릭했을 때는 노랑색
🖤 star에 마우스를 호버 했을 때는 회색
만들기 전에는 간단해 보여서 오래 걸리지 않겠다! 했지만, 역시나 이번에도 큰 오산이었다 🫠
📌 사용자가 정의한 start-rating 컨테이너 요소의 참조를 StarRating 함수에 전달해 star 요소들로 구성된 star-rating 요소를 동적으로 생성
const $containers = [...document.querySelectorAll('.star-rating')];
$containers.forEach($container => {
// star-rating 컨테이너 요소의 참조를 StarRating 함수에 전달해 star 요소들로 구성된 star-rating 요소를 동적 생성한다.
StarRating($container);
});
⭐️ StarRating 함수에서 for문을 돌려 star를 생성하고, 필요한 Event들을 추가하였다.
📌 star-rating 재사용 가능
<body>
<h1 class="title">Star rating</h1>
<div class="star-rating" data-max-rating="5"></div>
<div class="current-rating">current rating: <span>0</span></div>
<div class="star-rating" data-max-rating="3"></div>
<div class="current-rating">current rating: <span>0</span></div>
<div class="star-rating" data-max-rating="6"></div>
<div class="current-rating">current rating: <span>0</span></div>
</body>
⭐️ 별을 나타내는 'star-rating'과 사용자가 별을 클릭했을 때, 별의 개수를 나타내는 'current-rating'을 여러 개 만들어 사용할 수 있도록 구현하였다. (동영상에서 확인 😆)
📌 mouse Event에 따라 아래와 같은 효과 적용
🖤 star 요소에 마우스가 올라오면 해당 star 요소와 이전 star 요소 모두 color를 변경
🤍 star-rating 요소에서 마우스가 벗어나면 모든 star 요소의 color를 변경
💛 특정 star 요소를 클릭하면 해당 star 요소와 이전 star 요소 모두 color를 변경
✅ star mouseover
$container.addEventListener('mouseover', (e) => { }
✅ star mouseout
$container.addEventListener('mouseout', (e) => { }
✅ star click
$container.addEventListener('click', (e) => { }
💡 star에 효과를 주기 위해서는 사용자의 마우스가 현재 몇 번째 별에 위치해 있는지 알아야 하기 때문에,
Object.assign()을 사용하여 배열에 담고, forEach문으로 순회하였다.
변수를 하나 임의로 선언한 후, 마우스의 event.target으로 위치하는 별을 할당하여, 크기를 비교하였다.
사용자의 마우스 위치에 맞게 크기를 비교하면 만약 index가 3인 경우, 1 ~ 2까지의 index도 함께 선택될 수 있다.
📌 특정 star 요소의 rating을 커스텀 이벤트 'rating-change'를 통해 외부로 방출하고, 이를 캐치해 화면에 표시
const $containers = [...document.querySelectorAll('.star-rating')];
const $currentRatings = document.querySelectorAll('.current-rating > span');
$containers.forEach(($container, i) => {
StarRating($container);
$container.addEventListener('rating-change', e => {
const rating = e.detail;
$currentRatings[i].textContent = rating;
});
});
📌 여기서 CustomEvent란?
// CustomEvent 생성
const catFound = new CustomEvent('animalfound', {
detail: {
name: 'cat'
}
});
const dogFound = new CustomEvent('animalfound', {
detail: {
name: 'dog'
}
});
// 적합한 이벤트 수신기 부착
obj.addEventListener('animalfound', (e) => console.log(e.detail.name));
// 이벤트 발송
obj.dispatchEvent(catFound);
obj.dispatchEvent(dogFound);
// 콘솔에 "cat"과 "dog"가 기록됨
👉🏻 위에 예시는 mdn에서 가져온 예시이다.
✅ animalfound CustomEvent를 생성하여, dispatchEvent로 해당 detail 값을 넘긴다.
✅ addEventListener로 해당 CustomEvent를 사용하여 받은 detail 값을 출력하면 된다.
⭐️ 그럼 star-rating에서도 star의 rating을 'rating-change'를 통해 캐치하는 것이라면, 'rating-change'를 CustomEvent로 만들면 되지 않을까?!
따라서 'rating-change'라는 CustomEvnet를 아래와 같이 작성하여, +1 한 해당 index 값을 넘겨주어 화면에 출력하였다.
new CustomEvent('rating-change', {
detail: 변수
});
🫠 star-rating을 구현하면서 기본적인 mouse Event를 다뤄볼 수 있어 좋았고, 처음 알게 된 CustomEvent도 활용하는 기회가 되어서 좋았다. CustomEvent는 화면에 값을 출력하여 표시하고 싶을 때나 여러 상황에서 생각보다 많이 쓰일 것 같다.
star의 index를 활용해야겠다!라는 생각은 있었지만, 막상 코드를 짜려고 했을 때, 쉽게 그려지지 않아 조금 당황했다.
괜히 쫄아가지고.. 😭
각각 필요한 mouse Event를 작성했을 때, 중복되는 코드를 전역에서 따로 작성해서 함수로 사용할 수 있도록 구현했어도 코드가 더 간결하지 않았을까하는 아쉬움도 있다.
그래도 저번 Analog Clock을 만들 때, 재사용에 대해서 깊게 생각을 해봐서 이번 star-rating을 재사용할 수 있도록 구현하는 데에 있어서는 크게 문제가 없었다.
역시 경험이 중요해! 가장 기본적인 기능인 별점을 큰 문제없이 구현해 봐서 조금은 뿌듯하다 😆
참고자료 : https://developer.mozilla.org/ko/docs/Web/API/CustomEvent/CustomEvent
'프로젝트 > 토이 프로젝트' 카테고리의 다른 글
[React] 야구게임(BULLS AND COWS) (0) | 2023.04.28 |
---|---|
[javascript] News-Viewer (0) | 2023.04.24 |
[javascript] Calendar & DatePicker (0) | 2023.04.23 |
[javascript] AnalogClock (0) | 2023.04.06 |
[javascript] Toggle side navigation (0) | 2023.03.30 |