Я заметил, что offsetWidth
из this.ratingSliderInput = document.querySelector(".js-rating-slider-input")
изменяется случайным образом.
Он переходит от реальной ширины к переключению на 129
(не знаю, откуда это значение).
Это влияет на отрицательную настройку позиции this.ratingSliderThumb
.
Почему offsetWidth
изменяется случайным образом до 129?
JavaScript:
class RatingSlider {
constructor() {
this.ratingSliderForm = document.querySelector(".js-rating-slider-form");
this.ratingSliderInput = document.querySelector(".js-rating-slider-input");
this.ratingSliderThumb = document.querySelector(".js-rating-slider-thumb");
this.ratingSliderValue = document.querySelector(".js-rating-slider-value");
this.ratingSliderIcon = document.querySelector(".js-rating-slider-icon");
this.isPressed = false;
this.setEvents();
this.bind();
}
setEvents() {
this.moveEvent;
this.startEvent;
this.endEvent;
if ("ontouchstart" in document.documentElement) {
this.moveEvent = "touchmove";
this.startEvent = "touchstart";
this.endEvent = "touchend";
} else {
this.moveEvent = "mousemove";
this.startEvent = "mousedown";
this.endEvent = "mouseup";
}
}
setThumbStyle() {
this.ratingSliderIcon.style.transform = `scale(${1 +
this.ratingSliderInput.value / 150})`;
this.ratingSliderValue.innerText = `${this.ratingSliderInput.value}°`;
}
setPositionThumb() {
this.ratingSliderThumb.style.left = `${(this.ratingSliderInput.offsetWidth /
100) *
this.ratingSliderInput.value -
10}px`;
}
handleOffsetOnChange(event) {
if ("ontouchstart" in document.documentElement) {
let touch = event.touches[0] || event.changedTouches[0];
let target = document.elementFromPoint(touch.clientX, touch.clientY);
event.offsetX = touch.clientX - target.getBoundingClientRect().x;
}
if (
event.offsetX > 0 &&
event.offsetX < this.ratingSliderInput.offsetWidth
) {
this.ratingSliderThumb.style.left = `${event.offsetX - 10}px`;
}
}
bind() {
if (!this.ratingSliderForm) {
return;
}
this.setPositionThumb();
this.setThumbStyle();
this.ratingSliderInput.addEventListener(
this.startEvent,
() => (this.isPressed = true)
);
this.ratingSliderInput.addEventListener(this.endEvent, () => {
this.isPressed = false;
this.ratingSliderForm.submit();
});
this.ratingSliderInput.addEventListener(this.moveEvent, (event) => {
if (!this.isPressed) {
return;
}
this.handleOffsetOnChange(event);
this.setThumbStyle();
});
}
}
export default RatingSlider;
CSS:
.rating-slider__inner-container {
position: relative;
padding-top: 100px;
}
.rating-slider__input {
-webkit-appearance: none;
width: 100%;
height: 5px;
background: $form-gray;
&:focus {
outline: none;
}
}
.rating-slider__input::-webkit-slider-thumb {
-webkit-appearance: none;
background: transparent;
border-color: transparent;
height: 20px;
width: 20px;
margin-top: -8px;
cursor: pointer;
}
.rating-slider__input::-moz-range-thumb {
background: transparent;
border-color: transparent;
height: 20px;
width: 20px;
cursor: pointer;
}
.rating-slider__input::-moz-focus-outer {
border: 0;
}
.rating-slider__thumb {
display: flex;
flex-direction: column;
align-items: center;
position: absolute;
top: 50px;
left: -10px;
font-size: $text-3xl;
pointer-events: none;
}
.rating-slider__value {
color: $brand-primary;
font-size: $text-lg;
}
.rating-slider__range-labels-container {
display: flex;
justify-content: space-between;
}
Вот проект в прямом эфире: https://wagon-city-guides.herokuapp.com/spots/32
И код на GitHub:
JS: https://github.com/mirhamasala/lw_city_guide/blob/master/app/javascript/components/rating_slider.js
CSS: https://github.com/mirhamasala/lw_city_guide/blob/master/app/assets/stylesheets/components/_rating_slider.scss
HTML: https://github.com/mirhamasala/lw_city_guide/blob/master/app/views/spots/_spot_rating.html.erb