[MovieNight] ๐ŸŒŸ๋ณ„์  ๊ธฐ๋Šฅ ๊ตฌํ˜„

์ดˆ์ดยท2024๋…„ 5์›” 7์ผ
0

๐ŸฟMovieNight

๋ชฉ๋ก ๋ณด๊ธฐ
4/4
post-custom-banner

๐Ÿ–ฅ๏ธ ๊ตฌํ˜„ ํ™”๋ฉด


[โฌ†๏ธclick ํ™”๋ฉด]

[โฌ†๏ธmouseover ํ™”๋ฉด]



๐Ÿ› ๏ธ HTML ์ฝ”๋“œ



<div class="star-container">
  <label class="star-label">
    <input value="1" class="star-radio" type="radio" />
    <span class="star-icon"></span>
  </label>
  <label class="star-label">
    <input value="2" class="star-radio" type="radio" />
    <span class="star-icon"></span>
  </label>
  <label class="star-label">
    <input value="3" class="star-radio" type="radio" />
    <span class="star-icon"></span>
  </label>
  <label class="star-label">
    <input value="4" class="star-radio" type="radio" />
    <span class="star-icon"></span>
  </label>
  <label class="star-label">
    <input value="5" class="star-radio" type="radio" />
    <span class="star-icon"></span>
  </label>
</div>
  • star-container์•ˆ์— label ํƒœ๊ทธ 5๊ฐœ๋ฅผ ๋„ฃ๋Š”๋‹ค.
  • ๊ฐ label ํƒœ๊ทธ ์•ˆ์— input ํƒœ๊ทธ์™€ span ๋ฅผ ๋„ฃ๋Š”๋‹ค.
  • input ์€ ๋ผ๋””์˜ค ํƒ€์ž…์œผ๋กœ css์— display : none; ์œผ๋กœ ์ˆจ๊ธด๋‹ค.
  • ๊ทธ ์œ„์— span์œผ๋กœ ๋นˆ ๋ณ„ ์ด๋ฏธ์ง€๋ฅผ ๋„ฃ๋Š”๋‹ค.
  • input์˜ value์—๋Š” ๊ฐ 1~5์˜ ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค. (๊ทธ ๊ฐ’์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๊ฐ’์„ ์•Œ๊ธฐ์œ„ํ•ด.)


๐ŸŒŸ ๋ณ„ ์ฑ„์šฐ๊ธฐ/์ง€์šฐ๊ธฐ ํ•จ์ˆ˜



/** ๋ณ„ ์ฑ„์šฐ๊ณ  ์ง€์šฐ๊ธฐ ํ•จ์ˆ˜ */
//๋ณ„์  ์ฑ„์šฐ๊ธฐ
const fillStar = (value) => {
  for (let i = 0; i < value; i++) {
    starsList[i].classList.add("fill");
  }
};
//๋ณ„์  ์ง€์šฐ๊ธฐ
const removeFill = () => {
  for (let i = 0; i < 5; i++) {
    starsList[i].classList.replace("fill", "star-icon");
  }
};
  • fillStar ๋Š” ํด๋ฆญ/ํ˜ธ๋ฒ„ ํ•œ ๋ถ€๋ถ„์˜ value๋ฅผ ๋ฐ›์•„ ์ธ๋ฑ์Šค 0๋ถ€ํ„ฐ value๊ฐ’๊นŒ์ง€์˜ class ์ด๋ฆ„์„ fill๋กœ ๋ฐ”๊พธ์–ด์ฃผ๋Š” ํ•จ์ˆ˜๋‹ค.
    -> css์—์„œ fill์„ ์ฑ„์›Œ์ง„ ๋ณ„ ์ด๋ฏธ์ง€๋กœ ์„ค์ •ํ•œ๋‹ค.
  • removeFill ์€ 0๋ถ€ํ„ฐ 4๊นŒ์ง€(5๋ฒˆ) ๋ณ„์„ ๋‹ค ๋นˆ ๋ณ„๋กœ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ด๋‹ค.


๐ŸŒŸ ๋ณ„ ํด๋ฆญ ์ด๋ฒคํŠธ



const starsWrap = document.querySelector(".star-container");

//ํด๋ฆญํ•œ ๊ณณ ์ €์žฅํ•ด์ฃผ๋Š” ๋ณ€์ˆ˜
export let Checked = 0;

/**๋ณ„ ๋งˆ์šฐ์Šค ํด๋ฆญ */
//ํด๋ฆญ ์ด๋ฒคํŠธ ์‹œ ํด๋ฆญํ•œ ๋ณ„๊นŒ์ง€ ์ฑ„์›Œ์ง
starsWrap.addEventListener("click", (e) => {
  removeFill();
  fillStar(e.target.value);
  Checked = e.target.value;
});
  • star-container ๋ฅผ ํด๋ฆญ ํ• ๋•Œ, ํด๋ฆญ ํ•œ ๊ณณ์˜ target value ๋งŒํผ ๋ณ„์ด ์ฑ„์›Œ์ง€๊ฒŒ ํ•œ๋‹ค.
  • ์ด๋•Œ, checkํ•œ ๊ณณ์ด ์–ด๋”˜์ง€ ์ €์žฅํ•˜๊ฒŒ ํ•˜๋Š” Checked ๋ณ€์ˆ˜์— target์˜ value๋ฅผ ์ €์žฅํ•œ๋‹ค.(ํ›„์— ๋ฆฌ๋ทฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ๋ณ„์ ์„ ์–ผ๋งˆ๋‚˜ ์คฌ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด)


๐ŸŒŸ ๋ณ„ mouseover ์ด๋ฒคํŠธ



let starsList = document.querySelectorAll(".star-icon");

/** ๋ณ„ ๋งˆ์šฐ์Šค ํ˜ธ๋ฒ„ */
//๋งˆ์šฐ์Šค ํ˜ธ๋ฒ„ ์‹œ ๋ณ„์  ์ฑ„์šฐ๊ธฐ
starsWrap.addEventListener("mouseover", () => {
  starsList.forEach((star, idx) => {
    star.addEventListener("mouseenter", (e) => {
      removeFill();
      fillStar(idx + 1);
    });
  });
});
//๋งˆ์šฐ์Šค ํ˜ธ๋ฒ„๋ฅผ ์•ˆํ•  ๋•Œ, ์ „์— ํด๋ฆญํ•œ ๊ณณ๊นŒ์ง€
starsWrap.addEventListener("mouseout", () => {
  if (Checked !== 0) {
    removeFill();
    fillStar(Checked);
  } else {
    removeFill();
  }
});
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ star-container๋ฅผ mouseoverํ• ๋•Œ, ๋นˆ ๋ณ„ ์ด๋ฏธ์ง€๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” star-icon์„ 5๊ฐœ ๋‹ค ๋ถˆ๋Ÿฌ์™€์„œ starList๋กœ ์„ ์–ธํ•˜๊ณ  ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ ค์„œ ๊ฐ ์•„์ดํ…œ์— mouseenterํ•  ๋•Œ, removeFill()๋กœ ์ดˆ๊ธฐํ™” ํ•œ ๋’ค, fillStar(idx+1)๋กœ ํ˜ธ๋ฒ„ํ•œ ์ธ๋ฑ์Šค๋งŒํผ ์ฑ„์šด๋‹ค.
    -> ์ด๋•Œ, idx+1์ธ ์ด์œ ๋Š” ๋ณ„์˜ 0๋ฒˆ์งธ value๊ฐ€ 1๋กœ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ.
  • ๋˜ mouse๊ฐ€ ๋ฒ—์–ด๋‚˜๊ฒŒ ๋˜๋ฉด, ์ด์ „์— Checked์— ์ €์žฅํ•œ ๊ฐ’๋งŒํผ ์ฑ„์›Œ์ค€๋‹ค.



โ—์ˆ˜์ •์‚ฌํ•ญ

์ด๋ฏธ์ง€๋Š” ์ž„์‹œ๋กœ ์•„๋ž˜ ์ฃผ์†Œ์˜ velog์˜ ๋ณ„์„ ๊ฐ€์ ธ๋‹ค ์ผ๋‹ค. ํŒ€์›์ด ์•„์ด์ฝ˜ ์ž‘์—…์„ ๋งˆ์น˜๋ฉด ์ง„์งœ๋กœ ์™„์„ฑ!

๐Ÿ“— ์ฐธ๊ณ ์ž๋ฃŒ

https://velog.io/@jellykelly/rating

profile
๊ฐœ๋ฐœ ์ผ๊ธฐ์žฅ
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€