Как реализовать индикатор отображения числового параметра, как логарифмическая линейка?

Рейтинг: 2Ответов: 1Опубликовано: 10.01.2023

В WEB приложении нужно сделать индикатор температуры, похожий на движущуюся линейку. Принцип такой - горизонтально по экрану перемещается цифровая шкала (линейка), с отметками температуры. Температура растет - линейка движется справа налево, падает - слева направо. Скорость движения зависит от скорости изменения температуры. Посредине неподвижная стрелка, указывающая на текущую температуру. При попытке использовать в CSS transform: translate, появляется полоса прокрутки. Даже если ее "убрать", на смартфоне, а приложение предполагается использовать на смартфоне, появляется возможность двигать экран по горизонтали, что нехорошо. Температура от 20 до 100 градусов, цена деления шкалы 0,001 градус. Подскажите варианты реализации.

Ответы

▲ 2Принят

Исходя из описания, решение может быть следующим:

let elScale = document.querySelector('.scale');
for (let i = -150; i <= 150; ++i) {
  elScale.insertAdjacentHTML('beforeend', `<div>${i}</div>`);
}
document.querySelector('input[type="range"]').addEventListener('input', function(ev) {
  elScale.style.transform = `translatex(calc(${this.value * -50}px))`;
});
body {
  background-color: #ddd;
}

.thermostat {
  font: 16px/1em monospace;
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
}

.container {
  position: relative;
  display: flex;
  justify-content: center;
  width: 100%;
  border-radius: 5px;
  overflow: hidden;
  box-shadow: 1px 2px 2px 1px #fffd, -1px -2px 2px 1px #0004;
}

.container::before {
  content: '';
  position: absolute;
  z-index: 1;
  height: 100%;
  width: 100%;
  background-image: linear-gradient(to left, #0008 10px, #fff0 45%), linear-gradient(to right, #0008 10px, #fff0 45%);
}

.scale {
  display: flex;
  background-image: linear-gradient(to right, #04f4 0, #fff, #f405 100%);
  background-position: 50% 0;
  transition: transform .8s cubic-bezier(0.76, 0.72, 0.32, 1.14);
}

.scale div {
  font: bold 16px/1em monospace;
  display: grid;
  place-items: center;
  height: 3em;
  min-width: 50px;
  background: 50% 100% / 1px 10px linear-gradient( to right, #000 0 1px, #0000 1px 4px) no-repeat, 50% 0 / 1px 10px linear-gradient(to right, #000 0 1px, #0000 1px 4px) no-repeat, 0 100% / 5px 5px linear-gradient(to right, #000 0 1px, #0000 1px 4px) repeat-x, 0 0 / 5px 5px linear-gradient(to right, #000 0 1px, #0000 1px 4px) repeat-x;
}

.arrow {
  color: #ccc;
  filter: drop-shadow(0 -1px 0.5px #0008) drop-shadow(0 1px 0.5px #fff);
}
<div class="thermostat">
  <div class="container">
    <div class="scale"></div>
  </div>
  <div class="arrow">▲</div>
</div>
<input type="range" min="-20" max="100" step="0.001" value="0">