transition-like animation

by ShaCP

HTML

<p id="me" style="animation-duration: 3s" tabindex="-1">my animation code</p>
<div class="line line1">mid point</div>
<div class="line line2">end point</div>

CSS

#me {
  /* -webkit-animation: text-orientation-change 1s infinite linear; */
  /*   text-orientation: upright;
  writing-mode: vertical-rl; */
  /* transition: margin-left 1.5s linear; */
  border: 1px solid black;
  display: inline-block;
}

.line {
  width: 500px;
  height: 1px;
  background-color: red;
  position: absolute;
  top: 100px;
  color: red;
  font-size: 1rem;
  text-align: center;
}

.line2 {
  top: 200px;
}

#me.anim_on {
  animation: transform linear forwards;
  /* margin-left: 200px; */
  /* pointer-events: none; */
}

#me.reverse_anim {
  animation: transform_reverse linear forwards;
}

/* #me:focus {
  animation: margin-top 1.5s linear forwards;
} */


body {
  height: 100vh;
  font-size: 2rem;
  font-family: sans-serif;
}


@keyframes transform {
  to {
    transform: translateY(200px);
    /* margin-left: 200px; */
  }
}


@keyframes transform_reverse {
  to {
    transform: translate(0);
    /* margin-left: 200px; */
  }
}

JavaScript

const animationDuration = 3
let animationStartTime = 0;
let animationEndTime = 0;
let nextDuration = animationDuration;
let timeElapsedAtMouseIn;
let timeElapsedAtMouseOut;
let previousDuration = 0;
let prevNextDuration = 0;

const mouseIn = (e) => {
  /*1*/
  console.log("mouse in timestamp", performance.now() / 1000);
  const {
    x,
    y
  } = me.getBoundingClientRect();
  me.classList.remove("reverse_anim");
  /* new */
  animationStartTime = performance.now() / 1000;
  console.log("remove class to end anim timestamp (still in mouse in event)", animationStartTime);
  /* end  new */
  if (animationEndTime) {
    /* old but moved */
    me.style.transform = `translate(${x}px, ${y}px)`
    /* old but moved end */
    console.log(`mouse in time ${animationStartTime} - mouse out time ${animationEndTime}`);
    timeElapsedAtMouseIn = Math.min(animationStartTime - animationEndTime, animationDuration);
    console.log("time elapsed at mouse in", timeElapsedAtMouseIn);
    /* nextDuration */
    console.log(`nextDuration ${nextDuration} = previousDuration ${previousDuration} - timeElapsedAtMouseOut ${timeElapsedAtMouseOut} + timeElapsedAtMouseIn ${timeElapsedAtMouseIn}`);
    prevNextDuration = nextDuration;
    nextDuration = previousDuration - timeElapsedAtMouseOut + timeElapsedAtMouseIn;
    previousDuration = prevNextDuration;
    console.log("nextDuration", nextDuration);
    me.style["animation-duration"] = `${nextDuration}s`;
  }
  /* end nextDuration */
  /* end new */
  me.classList.add("anim_on");
}

const mouseOut = (e) => {
  /*3*/
  console.log("mouse out timestamp", performance.now() / 1000);
  const {
    x,
    y
  } = me.getBoundingClientRect();
  me.classList.remove("anim_on");
  animationEndTime = performance.now() / 1000;
  console.log("remove class to end anim timestamp (still in mouse out event)", animationEndTime);
  me.style.transform = `translate(${x}px, ${y}px)`;
  console.log(`mouse out time ${animationEndTime} - mouse in time...