Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Анимация графика (https://javascript.ru/forum/misc/77116-animaciya-grafika.html)

Влад Клыков 26.03.2019 13:24

Анимация графика
 
Всем доброго времени суток.
Была задача написать график, который будет реагировать на действия пользователя и плавно изменяться. При этом изменение может не успеть завершиться до следующего действия пользователя.
Я выбрал структуру, близку к React: переменная state с объектом, в котором хранятся данные, и по ним рисуется график. В state есть свойство animations, в которое добавлются "тикеты" - объекты, с указаниием какое свойство нужно анимировать. Функция animationLoop обрабатывает тикеты и вызывает функцию для перестройки графика. Код в сильно упрощенном виде:
const state = {
	x: 10,//значение, которое нужно анимировать
	animations: [],
	isAnimating: false
};
let animationID = null;

document.getElementById('button1').addEventListener(
	'click', change
);

function change() {
	//Добавление тикета в начало очереди
	state.animations.unshift({
		key: 'change',
		linkObject: state,
		name: 'x',
		startValue: state.x,
		endValue: 20,
		startTime: Date.now(),
		duration: 400
	});
	//Если анимация еще используется, начать её
	if(!state.isAnimating){
		animationLoop();
	}
}

function animationLoop() {
	state.isAnimating = true;
	let keysArr = [],
		now = Date.now();

	state.animations.forEach((item, i) => {
		let k = (now - item.startTime) / item.duration;

		//Проверка чтобы исколючить из двух и более тикетов с одинаковым ключом
		//оставить только последний зашедший, остальные убрать
		if(~keysArr.indexOf(item.key)) {
			state.animations.splice(i, 1);
		} else {
			keysArr.push(item.key);
		}

		//Присовение свойству объекта нужного значения
		item.linkObject[item.name] = item.startValue + 
			(item.endValue - item.startValue) * k;
	});

	drawGraphic();

	if(state.animations.length > 0) {
		animationID = requestAnimationFrame(animationLoop);
	} else {
		cancelAnimationFrame(animationID);
		state.isAnimating = false;
	}
}

function drawGraphic() {
	//отрисовка графика в canvas
}

Такой подход рабочий, но мне очень не нравится, что ссылка на значение, которое нужно поменять, пердается таким костыльным способом. Подскажите пожалуйста, как можно сделать это более красивым спосбом. Или требуется существенно поменять структуру?


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