首页 > 解决方案 > 元素的`offsetWidth`似乎随机变化

问题描述

我注意到offsetWidthofthis.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

标签: javascriptdom

解决方案


我意识到你的错误只出现在页面重新加载时,而不是来自另一个可疑的 turbolinks 是罪魁祸首(经常......)

所以我将此侦听器添加到您的app/javascript/packs/application.js

window.onload = function() {
  console.log("Window loaded")
  let ratingSliderInput = document.querySelector(".js-rating-slider-input");
  if(ratingSliderInput) {
  console.log("setPositionThumb", ratingSliderInput)
  console.log("setPositionThumb", ratingSliderInput.offsetWidth)
  }
}

在你的类似日志中setPositionThumb我得到了这个: 截屏 我猜turbolinks:load在显示完全到位之前事件可能会过早触发。


推荐阅读