<div class="box one"><i></i></div>*<div class="box two"><i></i></div>=<div class="box one two"><i></i></div>

<div class="debug"></div>

<button> Toggle the animation </button>

<div class="panel" >
<div>D1 - cubic-bezier(<input type="number" value="0.7" name="c11">,<input type="number" value="100" name="c12">,<input type="number" value="0.3" name="c13">,<input type="number" value="100" name="c14">) 
</div>
<div>D2 - cubic-bezier(<input type="number" value="0.5" name="c21">,<input type="number" value="100" name="c22">,<input type="number" value="1" name="c23">,<input type="number" value="-100" name="c24">) 
</div>
  <div>D1 - Initial value :<input type="number" value="0" name="d1i"> Final value :<input type="number" value="0.1" name="d1f"></div>
  <div>D2 - Initial value :<input type="number" value="0" name="d2i"> Final value :<input type="number" value="-0.1" name="d2f"></div>
</div>
@property --d1 {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}
@property --d2 {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

.box {
  display:inline-block;
  vertical-align: middle;
  width:150px;
  height:200px;
  margin:20px 10px;
  position:relative;
  border:1px solid;
  background:
    linear-gradient(blue 0 0) center/100% 1px no-repeat,
    linear-gradient(blue 0 0) center/1px 100% no-repeat;
}

.box i{
  content:"";
  position:absolute;
  z-index:9;
  width:10px;
  height:10px;
  border-radius:50%;
  background:radial-gradient(at 30% 30%,#0000,#000a) red;
  left:0;
  top:calc((50 + (var(--d1)*var(--d2)))*1%);
  transition:
    --d1 1s cubic-bezier(var(--c11,0.7),var(--c12,100),var(--c13,0.3),var(--c14,-100)),
    --d2 1s cubic-bezier(var(--c21,0.5),var(--c22,100),var(--c23,0.5),var(--c24,-100)),
    left 1s linear;
  transform:translate(-50%,-50%);
}
.start i {
  left:100%;
}
.one i {
  --d2:1; 
}
.two i {
  --d1:1; 
}
.one i {
  --d1:var(--d1i,0);
}
.two i {
  --d2:var(--d2i,0);
}
.start .one i {
  --d1:var(--d1f,0.1);
}
.start .two i {
  --d2:var(--d2f,-0.1);
}


body {
  font-size:50px;
  font-weight:bold;
  font-family:monospace;
}
/**/
d {position:fixed;height:4px;width:4px;background:#222;border-radius:50%}
button {border:none;border-radius:10px;padding:10px 20px;cursor:pointer;position:fixed;bottom:20px;right:20px;font-family:sans-serif;font-size:30px;background:#c82629;color:#fff;}
.panel {position: fixed;top: 20px;right: 20px;padding: 10px;border: 1px solid;border-radius: 10px;background: #ccc;font-family: sans-serif;opacity:.5;font-size:16px;}
.panel:hover {opacity:1}
.panel > div:not(:last-child) {border-bottom: 1px solid;padding-bottom: 10px;margin-bottom: 10px;}
.panel input {width:50px;}
let elem = document.querySelectorAll('i');
let inputs = document.querySelectorAll('input[type=number]');
let start;

function debug(timestamp) {
  if (start === undefined)
    start = timestamp;
  const elapsed = timestamp - start;
  for(var i=0;i<3;i++) {
    let rect = elem[i].getBoundingClientRect();   document.querySelector('.debug').insertAdjacentHTML("afterbegin",'<d style="top:'+(rect.y + rect.height/2)+'px;left:'+(rect.x + rect.width/2)+'px;"></d>')
 }
  if (elapsed < 1000) { 
    window.requestAnimationFrame(debug);
  }
}

document.querySelector("button").addEventListener("click",function() {
  document.body.classList.toggle("start");
  document.querySelector('.debug').innerHTML="&nbsp;";
  start=undefined;
  window.requestAnimationFrame(debug);
})


inputs.forEach(input => {
   input.addEventListener('change', function(e) {
      var p = e.target.getAttribute('name');
        document.body.style.setProperty("--"+p, this.value);
    });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.