ItsEvilTime
@ItsEvilTime
Сайленсер не дает мне покоя

Как сделать плавность движения блока при onmousemove?

Есть следующий код:
HTML:
<div id="block"></div>
CSS:
#block {
    width: 100px;
    height: 100px;
    background: teal;
    position: absolute;
}

JS:
var block = document.getElementById("block");

document.onmousemove = function(e) {
  block.style.left = (150 + e.pageX / 5) + "px"
  block.style.top = (100 + e.pageY / 5) + "px"
}

Этот код на JSFiddle: https://jsfiddle.net/xm08yyx5/
Все работает нормально до тех пор, пока мышку не увести за окно браузера. После возвращения в пределы окна - блок резко становится на место мышки.
Вопрос 1: Как сделать, чтобы блок плавно следовал к новому положению?
Пробовал добавить "transition: all .3s", но тогда блок стоит на месте и только после заданного в transition времени и полной остановке курсора начинает движение в конечное положение.

Вопрос 2: В браузерах IE, Edge и FF за блоком остаются полоски, которые сами по себе не исчезают. Но при принтскрине они не сохранились, поэтому есть мнение, что это только у меня. В этих браузерах у вас не остаются следы за блоком?

UPDATE
В качестве альтернативы написал движение за курсором по оси X с помощью requestAnimationFrame. Получилось так: https://jsfiddle.net/o0Lwmpr9/
Но в таком случае есть проблема с "затуханием" движения, в первом же примере с этим все в порядке. Т.е. в первом примере я просто поделил на 5 и границы движения стали меньше в 5 раз (строки 4 и 5). Во втором же случае деление на любое число (в строке 37) приводит к дерганному в разные стороны поведению.
Если задать фиксированные рамки, т.е.:
if (parseInt(block.style.left) < 200) { block.style.left = "200px" }

то в таком случае будет резкая остановка на границе, что не тот эффект, которого я хочу добиться.
Как можно обойти эту проблему?
  • Вопрос задан
  • 437 просмотров
Решения вопроса 2
ItsEvilTime
@ItsEvilTime Автор вопроса
Сайленсер не дает мне покоя
Написал решение для вопроса после UPDATE, т.е. тот же вопрос, но с использованием requestAnimationFrame.

block = document.getElementById("block");

animate = function(options) {
  var measure, start;
  start = performance.now();
  return requestAnimationFrame(measure = function(time) {
    var progress, timeFraction;
    timeFraction = (time - start) / options.duration;
    progress = options.timing(timeFraction);
    if (progress < 0) {
      progress = 0;
    }
    if (progress > 1) {
      progress = 1;
    }
    options.draw(progress);
    if (timeFraction < 1) {
      return requestAnimationFrame(measure);
    }
  });
};

block.style.left = "0";
block.style.top = "0";

document.onmousemove = function(e) {
  var dX, dY, lastX, lastY, theX, theY;
  lastX = parseInt(block.style.left);
  theX = e.pageX;
  dX = theX / 5 - lastX + 500;
  lastY = parseInt(block.style.top);
  theY = e.pageY;
  dY = theY / 5 - lastY + 200;
  return animate({
    duration: 100,
    timing: function(timeFraction) {
      return timeFraction;
    },
    draw: function(progress) {
      block.style.left = (lastX + progress * dX) + "px";
      return block.style.top = (lastY + progress * dY) + "px";
    }
  });
};

HTML и CSS тот же

Если нужна инверсия движения, то достаточно изменить вот эти строки:
dX = 500 - theX / 5 - lastX
dY = 200 - theY / 5 - lastY
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
grigruss
@grigruss
Пока не задал ни одного вопроса... только отвечаю.
Не знаю как в нативном JS, а в jQuery метод .animation().
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы