Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   requestAnimationFrame - замедление обьекта (https://javascript.ru/forum/misc/79403-requestanimationframe-zamedlenie-obekta.html)

potatosboxon 03.02.2020 19:13

requestAnimationFrame - замедление обьекта
 
Здравствуйте.

Код ниже демонстрирует ускоренеи элемента.

https://jsfiddle.net/sLy4dz7p/1/

<body style="background-color:#000;">
	<div id="test" style="position:absolute;top:50%;left:50%;transform:translate(50%,50%);width:20px;height:20px;background-color:#fff;"></div>
</body>
<script>
window.onload = function(){
	var element = document.getElementById('test');
	var start;	
	
	var minSpeed=1;
	var maxSpeed=5;
	var minPosY=0;
	var maxPosY=250;	
	var thisPosY=50;
	
	//Движение
	function moveMe(speed,pxY){
		//Шаг
		function step(timestamp){
			if (!start) {
				start = timestamp;
			};
			time=timestamp-start;
			var px = time * speed / 10;
			element.style.transform = "translate("+0+"px,"+px+"px)";
			if (px < pxY){
				requestAnimationFrame(step);
				speed=speed+0.5;
				return;
			}
			console.log("Приехали");
			return;
		}
		requestAnimationFrame(step);
	}
	moveMe(5,500);
}
</script>

Никак не могу решить задачу.
Необходимо плавно менять скорость перемещения относительно текущей позиции. То-есть если элемент находится на minPosY=0 то необходимо задать minSpeed=1, по мере увеличения Y в +, необходимо плавно наращивать скорость, пока она не станет равной 5 или не будет превышен maxPosY.

По существу, представим поле, сверху обьект движется с минимальной скоростью, внизу с максимальной. Между минимумом и максимумом скорость меняется плавно.

Help!

рони 03.02.2020 19:44

potatosboxon,
Структура анимации

ставите нужную Функцию расчёта времени(easing) и всё.

MallSerg 03.02.2020 19:45

google

или лучше https://learn.javascript.ru/js-anima...chyota-vremeni

potatosboxon 03.02.2020 19:51

А средствами чистого javascript этот вопрос никак не решить?

MallSerg 03.02.2020 20:08

А для тебя JS по всем приведенным ссылкам не достаточно чистый?
там даже каких либо подключенных библиотек нету =(.

potatosboxon 03.02.2020 21:33

Не крутил я animate. Он вроде как совсем новехенький.
Короч спутал я WEB Animate API и временную функцию.
В общем на сколько я сейчас разобрался, надо сделать следующее.
Найти начальную позицию.
Расчитать оставшееся время.
Задать параметры времеени и запустить элемент в путь.
Надо найти ease функцию.
Вот эта вроде как не то что надо
function inOutQuad(n){
    n *= 2;
    if (n < 1) return 0.5 * n * n;
    return - 0.5 * (--n * (n - 2) - 1);
};

Только не понятно, как каждый раз актуализировать оставшееся растояние, текущую позицию, и скоростью преодаления пути.

рони 03.02.2020 23:58

анимация блоков на js
 
potatosboxon,
<!DOCTYPE html>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
   body{
       background-color: hsla(0, 0%, 66%, 1);
       margin: 0;
   }

   div{
       display: inline-block;
   }

  </style>
  <script>
document.addEventListener( "DOMContentLoaded" , function() {
  function animate({timing, draw, duration}) {
  let start = performance.now();
  requestAnimationFrame(function animate(time) {
    let timeFraction = (time - start) / duration;
    if (timeFraction > 1) timeFraction = 1;
    let progress = timing(timeFraction);
    draw(progress);
    if (timeFraction < 1) {
      requestAnimationFrame(animate);
    }

  });
}
  function inOutQuad(n){
    n *= 2;
    if (n < 1) return 0.5 * n * n;
    return - 0.5 * (--n * (n - 2) - 1);
  };
  function easeOutExpo( t ) {

    if( t === 1 ) {
        return 1;
    }

    return ( -Math.pow( 2, -10 * t ) + 1 );

}
  class Boulder extends HTMLDivElement{
    constructor(color, left = 100, size = 15) {
		super();
		this.color = color;
        this.left = left;
		this.size = size;
		this.style.background = this.color;
		this.style.width = `${this.size}px`;
		this.style.height = `${this.size}px`;
        this.style.transform = `translate(${this.left}px, 0px)`;
        this.option = {timing : easeOutExpo, draw : this.draw.bind(this), duration : 5000};
        animate(this.option);
	}
    draw(progress){
        this.style.transform = `translate(${this.left}px, ${(window.innerHeight - this.size) * progress|0}px)`;
    }

  }
 customElements.define("custom-box", Boulder, { extends: "div" });

 for (let i = 0; i < 7; i++) {
    const color = '#' + ('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6);
    const left = (window.innerWidth - 15) * Math.random()|0;
    const box = new Boulder(color, left);
    document.querySelector("body").append(box);
 }


    });
 </script>
</head>
<body>
</body>
</html>

potatosboxon 04.02.2020 09:18

Че то не получается у меня точно сформулировать мысль. Надо подумать прежде чем вопрос задавать.
Надо начать с простого.
Пример демонстрирует ускорение.
function ease(n){
    return Math.pow(n, 2)
};
function startAnimation(){
    var element = document.getElementById('test');
	var stop = false;

    // animating x (margin-left) from 20 to 300, for example
    var startx = 0;
    var destx =  250;
    var duration = 1500;
    var start = null;
    var end = null;

    function startAnim(timeStamp) {
        start = timeStamp;
        end = start + duration;
        draw(timeStamp);
    }

    function draw(now) {
        if (stop) return;
        if (now - start >= duration) stop = true;
        var p = (now - start) / duration;
        val = ease(p);
        var px = startx + (destx - startx) * val;
        element.style.transform = "translate("+0+"px,"+px+"px)";
        requestAnimationFrame(draw);
    }

    requestAnimationFrame(startAnim);
}
startAnimation();

Как в данном случае замедлять элемент?

рони 04.02.2020 11:19

Цитата:

Сообщение от potatosboxon
замедлять элемент

смотрите пример выше #7, заменил inOutQuad на easeOutExpo.

potatosboxon 04.02.2020 11:36

Не решить мою задачу банальной t функцией.
Это хорошо эффектики всякие запускать, снежок там замедлять, ракету, но у меня совсем иная задача.
У меня сетка 5x5.
На 0:Y обьект должен перемещаться со скоростью 1.
На 5:Y обьект должен перемещаться со скоростью 5.
При движении от 0 к 5, от 5 к 0 - должна меняться скорость.
При перемещении по X скорость должна сохраняться заданная при перемещении по Y.
Спасибо за ответы, буду копать.

рони 04.02.2020 11:54

Цитата:

Сообщение от potatosboxon
На 0:Y обьект должен перемещаться со скоростью 1.
На 5:Y обьект должен перемещаться со скоростью 5.
При движении от 0 к 5, от 5 к 0 - должна меняться скорость.
При перемещении по X скорость должна сохраняться заданная при перемещении по Y.

не осилил.

Malleys 05.02.2020 10:50

Цитата:

Сообщение от potatosboxon
У меня сетка 5x5.
На 0:Y обьект должен перемещаться со скоростью 1.
На 5:Y обьект должен перемещаться со скоростью 5.
При движении от 0 к 5, от 5 к 0 - должна меняться скорость.

Т. е. вам нужно такое перемещение объекта, чтобы находясь в верхней части его скорость была 1 ячейка сетки / сек., а находясь в нижней части — 5 ячеек сетки / сек. Объект проходит 5 ячеек. Притом должно быть поступательное движение.

Давайте разбираться. Получается, что начальная скорость v₀ = 1, конечная скорость v₁ = 5. Объект начинает двигаться от точки s₀ = 0 и завершает своё движение в точке s₁ = 5. Движение начинается в момент времени t₀ = 0 и завершается в t₁, которое мы можем вычислить основываясь на том, что объект движется равноускоренно, т. е. ускорение a₀ постоянно.

Время окончания движения можно вычислить по формуле равноускоренного движения. Вычислив время завершения t₁, можно узнать ускорение a₀. Теперь у нас есть все константы, чтобы вычислить пройденный путь s и скорость v (для проверки) объекта в любой момент времени t.

Поскольку вас интересует только движение на отрезке времени [t₀; t₁], то можно через каждые t₁ - t₀ секунд оборачивать время вспять. Например при помощи обратных тригонометрических функции.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>

#grid {
	position: relative;
	width: 500px;
	height: 500px;
	background:
		repeating-linear-gradient(  0deg, var(--r)),
		repeating-linear-gradient(-90deg, var(--r));
	--c: 5;
	--w: 1px;
	--r: transparent 0 var(--w), rgba(0, 0, 0, 0.05) 0 calc(100% / var(--c));
}

#grid > .circle {
	width: 20px;
	height: 20px;
	background: yellowgreen;
	border-radius: 50%;
	margin: -10px 0 0 -10px;
	position: absolute;
	left: 50%;
}

#grid > .info::after {
	position: absolute;
	content: "v = " var(--v);
	white-space: nowrap;
	background: black;
	color: white;
	font: 1em monospace;
	border-radius: 0.25em;
	margin: 0.5em;
	padding: 0.2em 0.5em;
	right: 0;
	top: 0;
}

	</style>
</head>
<body>
	<div id="grid">
		<div class="info"></div>
		<div class="circle"></div>
	</div>

	<script>

const v0 = 1;
const v1 = 5;

const s0 = 0;
const s1 = 5;

const t0 = 0;
const t1 = 2 * s1 / (v0 + v1);

const a0 = (v1 - v0) / (t1 - t0);

function s(t) {
	return 0.5 * a0 * t ** 2 + v0 * t + s0;
}

function v(t) {
	return a0 * t + v0;
}

function F(x) {
	return t1 * (Math.acos(Math.cos(Math.PI * x / t1))) / Math.PI;
}

const circle = document.querySelector("#grid > .circle");
const info = document.querySelector("#grid > .info");
(function loop(time) {
	circle.style.transform = `translateY(${100 * s(F(time / 1000))}px)`;
	info.style.setProperty("--v", `"${v(F(time / 1000)).toFixed(2)}"`);

	requestAnimationFrame(loop);
})(performance.now());

	</script>
</body>
</html>


ЕЩЁ Упомянутые графики — https://www.desmos.com/calculator/dejdiypcao


Часовой пояс GMT +3, время: 00:31.