티스토리 뷰

 

라이브러리 없이 JS와 CSS로 price range를 만들어봤다.

찾다보니 input양쪽에 동글뱅이를 움직여서 실시간으로 가격변동이 가능한 코드들은 많았으나,

input동그라미 움직이기 + 클릭시 해당위치로 이동을 동시에 가능한 예시가 없어서 직접 구현해봤다 ㅠㅠ.

 

원하는기능 

1. 실시간으로 양쪽 동그라미를 움직이면 가격이 변동하는 기능

2. 클릭시에는 해당 위치로 이동하지만, 양쪽 range중에 가까운 range기준으로 움직이게끔

 

KakaoTalk_20221118_112053556.mp4
1.82MB

 

앵귤러 사용자기에 html과 css위주로 봐주세요!

<li class="filter-price-wrap">
                    <div class="filter-price-title">
                        <span [innerHTML]="'Common.Price'|translate">가격</span>
                    </div>

                    <div class="filter-price-display">
                        <span>{{withComma(minValue)}}<span
                                [innerHTML]="currencykey|translate">원</span></span>
                        <span>{{withComma(maxValue)}}<span
                                [innerHTML]="currencykey|translate">원</span></span>
                    </div>
                    <div id="range-slider" role="slider" class="filter-range-wrap"
                        (mouseup)="setPriceRange($event)">
                        <div class="filter-range-slider">
                            <input (input)="setPriceRange($event)" id="rangeMin" type="range"
                                min="0" max="100" value="0" />
                            <input (input)="setPriceRange($event)" id="rangeMax" type="range"
                                min="0" max="100" value="100" />

                            <div class="filter-slider">
                                <div class="filter-track"></div>
                                <div id="filter-range"></div>
                                <div id="thumb-left" class="filter-thumb">
                                </div>
                                <div id="thumb-right" class="filter-thumb"></div>
                            </div>
                        </div>


                    </div>
                </li>

 

 

이부분에서 range부분은 바로 이부분

range-slider다

<div id="range-slider" role="slider" class="filter-range-wrap"
                        (mouseup)="setPriceRange($event)">
                        <div class="filter-range-slider">
                            <input (input)="setPriceRange($event)" id="rangeMin" type="range"
                                min="0" max="100" value="0" />
                            <input (input)="setPriceRange($event)" id="rangeMax" type="range"
                                min="0" max="100" value="100" />

                            <div class="filter-slider">
                                <div class="filter-track"></div>
                                <div id="filter-range"></div>
                                <div id="thumb-left" class="filter-thumb">
                                </div>
                                <div id="thumb-right" class="filter-thumb"></div>
                            </div>
                        </div>

input은 2가지가 필요하다 오른쪽에 있는거, 왼쪽에 있는거 id부분을 보면 알수있지만 rangeMin과 rangeMax다.

여기서 기능을 달아줄부분은 3ㄱ4ㅏ지 input에도 setPricerange()가 있고, 가장 맨 위에 range-slider에도 setPriceRange()가 있다.

 

그밑에 filter-slider부분은 움직일시에 흰색부분말고 회색부분으로 표시해야될 부분과, range바

 

 

바로 요모양이다!

.filter-range-wrap {
    position: relative;
    width: 236px;
    margin: 0 auto;
    height: 5px;
    padding: 15px 0;
    cursor: pointer;
    margin-top: 40px;
    padding-bottom: 10px;
}

.filter-slider {
    position: relative;
    z-index: 1;
    height: 2px;
}

.filter-track {
    position: absolute;
    z-index: 1;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    background-color: #7E8B98
}

#filter-range {
    position: absolute;
    z-index: 2;
    left: 0%;
    right: 0%;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    background-color: #fff;
}

.filter-thumb {
    position: absolute;
    z-index: 3;
    width: 10px;
    height: 10px;
    background-color: #fff;
    border-radius: 50%;
    top: -4px;
}

#thumb-left {
    left: 0%;
}

#thumb-right {
    right: 0%;
}


input[type="range"] {
    position: absolute;
    pointer-events: none;
    appearance: none;
    -webkit-appearance: none;
    z-index: 2;
    height: 4px;
    width: 237px;
    left: -4px;
    opacity: 0;
    top: 12px;
}

input[type="range"]::-webkit-slider-thumb {
    pointer-events: all;
    width: 15px;
    height: 15px;
    background-color: red;
    border-radius: 50%;
    top: 6px;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}

 

setPriceRange(event: Event | MouseEvent) {
        const minInput = (document.getElementById('rangeMin') as HTMLInputElement);
        const maxInput = (document.getElementById('rangeMax') as HTMLInputElement);

        const thumbLeft = (document.getElementById('thumb-left') as HTMLDivElement);
        const thumbRight = (document.getElementById('thumb-right') as HTMLDivElement);
        const range = (document.getElementById('filter-range') as HTMLDivElement);

        const target = (event.target as HTMLInputElement);
        const [min, max] = [parseInt(target.min), parseInt(target.max)];

        const current = Math.floor((event as MouseEvent).clientX);
        const position = ((current - this.left) * 10) / this.width;
        const average = (Number(minInput.value) + Number(maxInput.value)) / 2;
        let targetPercent = Math.ceil(position * 10);

        if (target.id === 'rangeMin') {

            (event.target as HTMLInputElement).value = String(Math.min(parseInt(target.value), parseInt(maxInput.value) - 10));

            const percent = Math.ceil(((Number(target.value) - min) / (max - min)) * 100);
            thumbLeft.style.left = percent + "%";
            range.style.left = percent + "%";

            this.minValue = this.setPrice(Number(target.value) * this.priceGap);
            this.searchCondition.minprice = this.minValue;
            this.searchCondition.maxprice = this.maxValue;

        } else if (target.id === 'rangeMax') {
            (event.target as HTMLInputElement).value = String(Math.max(parseInt(target.value), parseInt(minInput.value) + 10));

            const percent = Math.ceil(((Number(target.value) - min) / (max - min)) * 100);
            thumbRight.style.right = 100 - percent + "%";
            range.style.right = 100 - percent + "%";

            this.maxValue = this.setPrice(Number(target.value) * this.priceGap);
            this.searchCondition.maxprice = this.maxValue;
            this.searchCondition.minprice = this.minValue;
        } else {
            if (targetPercent < 0) {
                minInput.value = '0';
                thumbLeft.style.left = 0 + "%";
                range.style.left = 0 + "%";
                this.minValue = 0;
                this.searchCondition.minprice = 1;
                this.updateSearchCondition();
                return;
            } else if (targetPercent > 100) {
                maxInput.value = '100';
                thumbRight.style.right = 0 + "%";
                range.style.right = 0 + "%";
                this.maxValue = this.setPrice(100000);
                this.searchCondition.maxprice = this.maxValue;
                this.updateSearchCondition();
                return;
            }
            //들어오는 position값이 현재 input위치들의 average 중간값보다 큰지 아닌지 구하는 이유?
            //-> 왼쪽 input에 가까운지 오른쪽 output에 가까운지를 계산하여 가까운쪽의 input을 이동시키기위하여
            if (targetPercent < average) {
                if (targetPercent < 0) {
                    minInput.value = '0';
                    thumbLeft.style.left = 0 + "%";
                    range.style.left = 0 + "%";
                    this.minValue = 0;
                    this.searchCondition.minprice = 1;
                    this.updateSearchCondition();
                    return;
                }
                targetPercent = Math.min(targetPercent, parseInt(maxInput.value) - 10);
                minInput.value = String(targetPercent);
                thumbLeft.style.left = targetPercent + "%";
                range.style.left = targetPercent + "%";

                this.minValue = this.setPrice(targetPercent * this.priceGap);

                if (this.minValue === 0) {
                    this.searchCondition.minprice = 1;
                    this.searchCondition.maxprice = this.maxValue;
                } else {
                    this.searchCondition.minprice = this.minValue;
                    this.searchCondition.maxprice = this.maxValue;
                }

            } else {
                targetPercent = Math.max(targetPercent, parseInt(minInput.value) + 10);
                maxInput.value = String(targetPercent);
                thumbRight.style.right = 100 - targetPercent + "%";
                range.style.right = 100 - targetPercent + "%";

                this.maxValue = this.setPrice(targetPercent * this.priceGap);
                this.searchCondition.minprice = this.minValue;
                this.searchCondition.maxprice = this.maxValue;
            }
        }

        if (event.type === 'mouseup') {
            this.updateSearchCondition();
        }
    }

설..설명은 나중에 정리해서올려야겟다

급귀찮..

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함