Использование translate3d и масштабирования для преобразований

Я хотел сделать div, который следует за курсором и одновременно увеличивается/уменьшается как анимация.
Я изменил положение div с помощью top и left, но анимация иногда немного прерывистая.

Я хотел использовать translate3d, чтобы сделать анимации плавными, но не могу совместить translate3d с scale

const moveCursor = event => {
    const cursorWidth = cursor.offsetWidth / 2;
    cursor.style.left = event.pageX - cursorWidth + "px";
    cursor.style.top = event.pageY - cursorWidth + "px";
};  

Я хотел изменить эту функцию, чтобы использовать translate3d вместо top и left и сохранить существующие значения преобразования scale из анимации.

Я придумал это, но это не работает

const moveCursor = event => {
    const cursorWidth = cursor.offsetWidth / 2;
    const xCoordinate = event.pageX - cursorWidth + "px";
    const yCoordinate = event.pageY - cursorWidth + "px";

    const matrix = window.getComputedStyle(cursor).transform;
    const scalingFactor = parseFloat(matrix.split(",")[3]);

    cursor.style.transform = `translate3d(${xCoordinate},${yCoordinate},0px) scale(${scalingFactor})`
};

Где я ошибаюсь?

const cursor = document.getElementById("cursor");
const moveCursor = event => {
  const cursorWidth = cursor.offsetWidth / 2;
  cursor.style.left = event.pageX - cursorWidth + "px";
  cursor.style.top = event.pageY - cursorWidth + "px";
};
document.addEventListener("mousemove", moveCursor);
#background {
  position: relative;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  background-color: #0e0e0e;
  color: ivory;
  font-size: 3rem;
  text-align: center;
}

#cursor {
  width: 15rem;
  height: 15rem;
  will-change: transform;
  background: ivory;
  position: absolute;
  mix-blend-mode: difference;
  border-radius: 50%;
  animation: grow-shrink 4s infinite alternate;
}

@keyframes grow-shrink {
  0% {
    transform: scale(1.2);
  }
  25% {
    transform: scale(0.8);
  }
  50% {
    transform: scale(1.2);
  }
  75% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}
<div id="background">
  Lorem Ipsum
  <div id="cursor"></div>
</div>


person prateek    schedule 27.07.2020    source источник


Ответы (1)


Анимация переопределит значения, которые вы установили с помощью elem.style.
Чтобы обойти это, вы можете добавить элемент-оболочку только для перевода и сохранить анимацию масштаба для обернутого элемента, или вы должны были иметь возможность использовать переменные css для обновления. значения перевода в анимации, за исключением того, что Chrome не обновляет анимацию, я не знаю, по каким причинам:

Этот фрагмент будет работать только в Firefox

const cursor = document.getElementById("cursor");
const moveCursor = event => {
  const cursorWidth = cursor.offsetWidth / 2;
  cursor.style.setProperty( '--translate-x', event.pageX - cursorWidth + "px" );
  cursor.style.setProperty( '--translate-y', event.pageY - cursorWidth + "px" );
;}
document.addEventListener("mousemove", moveCursor);
#background {
  position: relative;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  background-color: #0e0e0e;
  color: ivory;
  font-size: 3rem;
  text-align: center;
}

#cursor {
  width: 15rem;
  height: 15rem;
  will-change: transform;
  background: ivory;
  position: absolute;
  mix-blend-mode: difference;
  border-radius: 50%;
  animation: grow-shrink 4s infinite alternate;
  --translate-x: 0px;
  --translate-y: 0px;
  --translate: translate( var(--translate-x), var(--translate-y) );
}

@keyframes grow-shrink {
  0% {
    transform: var(--translate) scale(1.2);
  }
  25% {
    transform: var(--translate) scale(0.8);
  }
  50% {
    transform: var(--translate) scale(1.2);
  }
  75% {
    transform: var(--translate) scale(0.8);
  }
  100% {
    transform: var(--translate) scale(1);
  }
}
<div id="background">
  Lorem Ipsum
  <div id="cursor"></div>
</div>

Итак, у нас остается решение-оболочка:

const cursor = document.getElementById("trans-wrapper");
const moveCursor = event => {
  const cursorWidth = cursor.offsetWidth / 2;
  cursor.style.left = event.pageX - cursorWidth + "px";
  cursor.style.top = event.pageY - cursorWidth + "px";
};
document.addEventListener("mousemove", moveCursor);
#background {
  position: relative;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  background-color: #0e0e0e;
  color: ivory;
  font-size: 3rem;
  text-align: center;
}

#cursor {
  width: 15rem;
  height: 15rem;
  will-change: transform;
  background: ivory;
  border-radius: 50%;
  animation: grow-shrink 4s infinite alternate;
}
#trans-wrapper {
  width: 15rem;
  height: 15rem;
  will-change: transform;
  position: absolute;
  mix-blend-mode: difference;  
}


@keyframes grow-shrink {
  0% {
    transform: scale(1.2);
  }
  25% {
    transform: scale(0.8);
  }
  50% {
    transform: scale(1.2);
  }
  75% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}
<div id="background">
  Lorem Ipsum
  <div id="trans-wrapper">
    <div id="cursor"></div>
  </div>
</div>

person Kaiido    schedule 27.07.2020
comment
Работает как шарм, спасибо - person prateek; 27.07.2020