【问题标题】:`offsetWidth` of element seems to change randomly元素的`offsetWidth`似乎随机变化
【发布时间】:2020-04-10 09:07:22
【问题描述】:

我注意到this.ratingSliderInput = document.querySelector(".js-rating-slider-input")offsetWidth 随机变化。

它从实际宽度切换到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

【问题讨论】:

  • 我试图打开站点,但是每次都显示登录页面时无法调试,对不起。有没有办法禁用它?
  • 我没有考虑到这一点。不过,恐怕不会。因为您需要登录才能留下评分。

标签: javascript dom


【解决方案1】:

我意识到您的错误只出现在页面重新加载时,而不是来自另一个可疑的 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 事件可能在显示完全到位之前过早触发。

【讨论】:

    猜你喜欢
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2011-04-18
    • 2016-04-05
    • 2018-05-30
    相关资源
    最近更新 更多