Анимировать элемент в Javascript при перемещении мыши - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть два DIV различной ширины друг на друга.Верхний DIV displayDIV шире нижнего DIV captureDIV.

. В displayDIV я рисую точку, положение X которой пропорционально положению мыши в пределах captureDIV.

Когда вы перемещаете мышь в captureDIV, точка перемещается пропорционально в DisplayDIV.

Это имеет гораздо больше смысла, если вы посмотрите на эту скрипку

Мой код выглядит следующим образом ...

let capture = document.getElementById('captureDIV');
let display = document.getElementById('displayDIV');
let circle = document.getElementById('circle');
capture.addEventListener('mousemove', handleMouseMove);

function handleMouseMove(event) {
  const captureRect = capture.getBoundingClientRect();
  const captureWidth = captureRect.right - captureRect.left;
  const relativeX = event.x - captureRect.left;
  let percent = (relativeX / captureWidth) * 100;
  let roundedPercent = parseFloat(Math.round(percent * 100) / 100).toFixed(2);

  moveDotTo(roundedPercent);
}


function moveDotTo(percentage) {
  const displayRect = display.getBoundingClientRect();
  const displayWidth = displayRect.right - displayRect.left;
  const circleX = displayRect.left + displayWidth * (percentage / 100);
  const circleY = displayRect.top + (displayRect.height / 2);
  const style = `top:${circleY}px;left:${circleX}px;`;
  circle.setAttribute('style', style);
}

У меня также есть несколько кнопок, с помощью которых можно установить положение точки в DisplayDIV, например ...

let move20 = document.getElementById('move20');
move20.addEventListener('click', function(event) {
  moveDotTo(20);
});

Используя Vanilla JS, а не приемы CSS, как я могу создать функцию для анимации (а не перемещения) точки из ее существующего положения в новое положение.

function animateDotTo(percentage) {
  // clever code here
}

Мне нужно иметь возможность вызыватьфункция animateDotTo(percentage) с помощью кнопки или обработчика события mousemove.

Точка всегда должна анимироваться в своей новой позиции независимо от того, как происходит движение.Например, если мышь перемещается из левой стороны captureDIV вокруг нижней части, а затем в правую сторону captureDIV, точка должна анимироваться по DisplayDIV, а не прыгать, как сейчас.Равным образом нажатие одной из кнопок move to x% должно оживить точку от ее текущей позиции до новой.

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Если вы рисуете круг и перемещаете его, я бы предложил нарисовать элемент <canvas> вместо перемещения <div>, установив его свойства top и left.Даже использование transform: translate(x, y) может быть лучше.

Чтобы плавно перевести вашу точку из одного местоположения в другое, используя JavaScript, вы захотите:

  • Текущее положение точки как x и y координаты,
  • Целевая позиция точки в виде x и y координат, а также
  • Скорость, с которой точка движется как скаляр.

Обновление текущей позиции выполняется в каждом кадре анимации с помощью window.requestAnimationFrame.Имея это в виду и способ применения полученной вычисленной позиции к точке, вы можете использовать такой метод: Как переместить объект с использованием координат X и Y в JavaScript , чтобы переместить вашу точку (пример перемещает холст, но если вы знаете x и y, тогда вы можете установить для них top и bottom).

0 голосов
/ 29 ноября 2018

Отвечая на мой собственный вопрос, спасибо Билли Брауну за указание в правильном направлении.Использование window.requestAnimationFrame это путь.

var currentPercentage;
var startPercentage;
var targetPercentage;


function animateDotTo(percentage) {
    targetPercentage = percentage;
    startPercentage = currentPercentage;
    window.requestAnimationFrame(step);
}

function step(timestamp) {
    var fps = 7;
    var maxStep = 30;
    var distStartToTarget = Math.abs(startPercentage - targetPercentage);
    var stepSize = Math.min(distStartToTarget / fps, maxStep);
    if (targetPercentage < startPercentage) {
        currentPercentage -= stepSize,0;
        if (currentPercentage > targetPercentage) {
            window.requestAnimationFrame(step);
        }
    } else if (targetPercentage > startPercentage) {
        currentPercentage += stepSize,100;
        if (currentPercentage < targetPercentage) {
            window.requestAnimationFrame(step);
        }
    } else {
        return;
    }
    if (currentPercentage > 100 ) { currentPercentage = 100; }
    if (currentPercentage < 0 ) { currentPercentage = 0; }
    moveDotTo(currentPercentage);
}

Обновлено Скрипка

0 голосов
/ 29 ноября 2018

Простой трюк в css-переходе исправит это.

Конечно.Вы не хотите, чтобы это оживляло, когда вы фактически двигаете мышь.Поэтому я отделил свойство css для перехода от другого класса, а затем удалил этот класс при перемещении мыши, повторно прикрепив его при нажатии кнопок перемещения.

CSS

#circle {
  position: absolute;
  left: -100px;
  top: -100px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #000;

  transition: none;
}

#circle.animate{
    transition: 500ms ease;
}

JS

move20.addEventListener('click', function(event) {
  moveDotTo(20); animateDotTo();
});

move60.addEventListener('click', function(event) {
  moveDotTo(60);animateDotTo();
});

move80.addEventListener('click', function(event) {
  moveDotTo(80);animateDotTo();
});

function moveDotTo(percentage) {
    circle.classList.remove("animate");

  const displayRect = display.getBoundingClientRect();
  const displayWidth = displayRect.right - displayRect.left;
  const circleX = displayRect.left + displayWidth * (percentage / 100);
  const circleY = displayRect.top + (displayRect.height / 2);
  const style = `top:${circleY}px;left:${circleX}px;`;
  circle.setAttribute('style', style);
}

function animateDotTo(percentage) {
    circle.classList.add("animate");
}

http://jsfiddle.net/8pm2grjd/

Если вы хотите, чтобы он анимировался, даже если вы запускаете движение с помощью мышки, вы можете игнорировать подход класса и просто добавить свойство перехода наCSSНо это будет имитировать раздражающий эффект задержки мыши, аналогичный задержке ввода в видеоиграх из-за V-Sync.

...