<div id="moved" style="position: absolute;width:30px;height: 30px;background: red;"></div>
<br>
<input type="button" onclick="but1()" value="кнопка 1"> <br>
<script type="text/javascript">
let nclick = 0;
const animparams = [
[800 , 100 , 3000],
[-750 , 10 , 200],
[150 , -60 , 2000],
[-200 , -50 , 1000]
];
let animPromise = Promise.resolve();
function but1 (){
const element = document.getElementById("moved");
animPromise = animPromise.then (() => animateMove( element , ...animparams[(nclick++) % 4]));
}
function animateMove ( element , x , y , time = 1000){
const startX = element.offsetLeft;
const startY = element.offsetTop;
const startTime = performance.now();
return new Promise ( (resolve) => {
const animate = function (timenow){
let EA = (timenow - startTime) / time;
if (EA > 1) EA = 1;
element.style.left = startX + (x * EA) + "px";
element.style.top = startY + (y * EA) + "px";
if (EA == 1) {
resolve()
} else {
requestAnimationFrame(animate );
}
};
animate(startTime);
})
}
</script>
Жмите когда хотите и сколько хотите.
Можно и нормальную очередь сделать, хотя бы самую простую с помощью массива и операций push/shift. Добавлять в нее параметры следующей анимации и когда предыдущая закончится вытаскивать следующую. Ту главное принцип - ловить окончание анимации с помощью Promise.