Price Range-Slider 구현

혜진 조·2023년 4월 10일
0

리액트

목록 보기
25/31
post-custom-banner

PriceRange.tsx

import { useState } from "react";
import "./PriceRange.scss";

export const PriceRange = () => {
  let fixedMinPrice = 0;
  let fixedMaxPrice = 5000000;
  let priceGap = 100000;
  const [minValue, setMinValue] = useState(fixedMinPrice);
  const [maxValue, setMaxValue] = useState(fixedMaxPrice);
  const [rangeMinPercent, setRangeMinPercent] = useState(0);
  const [rangeMaxPercent, setRangeMaxPercent] = useState(0);

  const minValueHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMinValue(parseInt(e.target.value));
  };
  const maxValueHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMaxValue(parseInt(e.target.value));
  };

  const twoRangeHandler = () => {
    if (maxValue - minValue <= priceGap) {
      if (fixedMaxPrice <= maxValue + priceGap) {
        setMinValue((prev) => prev - priceGap);
        setMaxValue(fixedMaxPrice);
      } else if (fixedMinPrice >= minValue - priceGap) {
        setMinValue(fixedMinPrice);
        setMaxValue((prev) => prev + priceGap);
      } else {
        setMinValue((prev) => prev - priceGap);
        setMaxValue((prev) => prev + priceGap);
      }
    } else {
      setRangeMinPercent(() => (minValue / fixedMaxPrice) * 100);
      setRangeMaxPercent(() => 100 - (maxValue / fixedMaxPrice) * 100);
    }
  };
  return (
    <div id="PriceRange">
      <section className="text_input_wrap">
        <input type={"text"} className="min_price_text" value={minValue} />
        <span>~</span>
        <input type={"text"} value={maxValue} />
      </section>

      <div className="price_slider">
        <div
          className="inner_range"
          style={{ left: `${rangeMinPercent}%`, right: `${rangeMaxPercent}%` }}
        ></div>
        {/* <div className="input_range_wrap"> */}
        <input
          className="min_price"
          type={"range"}
          value={minValue}
          step="100000"
          min={fixedMinPrice}
          max={fixedMaxPrice}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            minValueHandler(e);
            twoRangeHandler();
          }}
        />
        <input
          className="max_price"
          type={"range"}
          step="100000"
          value={maxValue}
          min={fixedMinPrice}
          max={fixedMaxPrice}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            maxValueHandler(e);
            twoRangeHandler();
          }}
        />
        {/* </div> */}
      </div>
    </div>
  );
};

PriceRange.scss

#PriceRange {
  .text_input_wrap {
    display: flex;
    align-items: center;
    span {
      margin: 0 10px;
    }
  }
  //배경
  .price_slider {
    margin-top: 45px;
    position: relative;
    height: 4px;
    width: 100%;
    border-radius: 10px;
    background-color: #dddddd;
    &::before {
      content: "0";
      position: absolute;
      left: 0;
      top: -35px;
    }
    &::after {
      content: "500만원";
      position: absolute;
      right: 0;
      top: -35px;
    }
    //현재값
    .inner_range {
      position: absolute;
      top: 0;

      //   left: 30%;
      //   right: 30%;
      height: 4px;
      border-radius: 10px;
      background-color: #b0b0b0;
    }
    input {
      position: absolute;
      background: none;
      top: 0;
      // background-color: darkgray;
      height: 3px;
      // color: aliceblue;
      width: 100%;
      --webkit-appearance: none;
      pointer-events: none; //버튼 비활성화

      //버튼 커스텀
      &.min_price::-webkit-slider-thumb {
        pointer-events: auto; //커스텀 버튼 활성화
        height: 30px;
        width: 30px;
        border-radius: 50%;
        border: 2px solid #b0b0b0;
        background-color: white;
        -webkit-appearance: none;
      }
      &.max_price::-webkit-slider-thumb {
        pointer-events: auto; //커스텀 버튼 활성화
        height: 30px;
        width: 30px;
        border-radius: 50%;
        border: 2px solid #b0b0b0;
        background-color: white;
        -webkit-appearance: none;
      }
    }
  }
}
profile
나를 믿고 한 걸음 한 걸음 내딛기! 🍏
post-custom-banner

0개의 댓글