Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   ООП. Летящие пули (https://javascript.ru/forum/misc/63439-oop-letyashhie-puli.html)

Bond 07.06.2016 22:10

ООП. Летящие пули
 
Всем здравствуйте.
Задача состоит в следующем - при определенном событии - а нашем случае при клике на кнопку нужно создать элемент( к примеру пулю) и заставить ее двигаться - а при определенном условии (в нашем случае при пролете пули 1000 пикселей) удалить анимацию которая ее двигала и саму пулю (элемент)
Все это я реализовал так http://1.top-start.ru/bullet/
Вот код скомпилированный с TypeScript:
var Bullet = (function () {
    function Bullet() {
        this.element = document.getElementById('transline');
        this.create();
    }
    Bullet.prototype.create = function () {
        this.childElement = document.createElement("li");
        this.element.appendChild(this.childElement);
        this.move();
    };
    Bullet.prototype.move = function () {
        var left = 0;
        var _this = this;
        var move = setInterval(function () {
            _this.childElement.style.left = (left += 4) + "px";
            if (left > 1000) {
                clearInterval(move);
                _this.childElement.remove();
            }
        }, 10);
    };
    return Bullet;
}());
var button2 = document.getElementById("create");
button2.addEventListener('click', function () {
    new Bullet();
});


То есть имеется класс описывающий пулю, а при клике создается объект который все реализовывает для каждой отдельной пули.
Вопрос в следующем - правильный ли это подход?
Если да то получается при каждом клике создается объект - при достижении условия удаляется анимация и элемент изображающий пулю но сам объект остается - надо ли его удалять и если да то как? Ведь этих объектов теоретически может быть десятки а то и сотни тысяч.

Если мой подход неверный то как сделать что бы можно было создать один объект и что бы он управлял всеми пулями
В нашем случае это должно работать
var bullet = new Bullet();
var button2 = document.getElementById("create");
button2.addEventListener('click', function() {
	bullet.create();
});

Изначально так и думал сделать - но не получилось - там проблемы с setInterval возникает и все криво работает.
Буду признателен за помощь.

Rise 07.06.2016 23:27

Цитата:

Сообщение от Bond (Сообщение 418751)
но сам объект остается

Мне кажется если на него нет ссылок то он удалится автоматически.

Coriolan161 07.06.2016 23:27

Bond,
Ты пишешь надо ли удалять объект... как удалить объект в этом языке?

Bond 08.06.2016 00:41

Rise, так и есть, поразбирался, погуглил, в коде поставил создание 10 объектов через каждые 100 мс за один клик - запустил в отладчике посмотрел - вроде все гуд, память очищается почти сразу же.

Coriolan161, ну может не сам объект а ссылки на него через delete.
А вообще имел ввиду стоит ли в моей ситуации заботиться о памяти и т.д

Rise 08.06.2016 18:12

Цитата:

Сообщение от Bond (Сообщение 418751)
В нашем случае это должно работать
var bullet = new Bullet();
var button2 = document.getElementById("create");
button2.addEventListener('click', function() {
	bullet.create();
});

var Bullet = (function () {
	function Bullet() {
		this.element = document.getElementById('transline');
		this.bullet = document.createElement('li');
	}
	Bullet.prototype.create = function () {
		setTimeout(function move (bullet, left) {
			left = Math.min(left + 4, 1000); bullet.style.left = left + 'px';
			if (left == 1000) bullet.remove(); else setTimeout(move, 10, bullet, left);
		}, 10, this.element.appendChild(this.bullet.cloneNode(true)), 0);
	};
	return Bullet;
}());

ruslan_mart 08.06.2016 19:53

Bond, move вынести наружу и забиндить, иначе он каждый раз заново создаётся, что не есть хорошо.

var Bullet = (function() {
	function Bullet() {
		this.element = document.getElementById('transline');
		this.bullet = document.createElement('li');
		this.left = 0;
		this._move = this.move.bind(this);
	}
	Bullet.prototype.create = function() {
		setTimeout(this._move, 10);
	};
	Bullet.prototype.move = function() {
		this.left += 4;
		this.bullet.style.left = this.left + 'px';
		if(this.left >= 1000) this.remove();
		else setTimeout(this._move, 10);
	};
	Bullet.prototype.remove = function() {
		this.bullet.remove();
		this.left = 0;
	};
	return Bullet;
}());


Также советую почитать про requestAnimationFrame.

Rise 09.06.2016 03:01

Ruslan_xDD, не работает

Bond 09.06.2016 06:15

Rise,
спасибо за код, только не совсем понял как это работает. Понял что это рекурсивный setTimeout, но как он потом убивается - при удалении элемента? И не будет ли проблем если мне нужно будет не удалить элемент пулю, а остановить?
Ruslan_xDD, спасибо почитаю про requestAnimationFrame. Вернее уже почитал разобраться надо.

ruslan_mart 09.06.2016 10:13

Bond, думаю, вот так лучше будет:

var Bullet = (function() {
	function Bullet() {
		this.element = document.getElementById('transline');
		this.bullet = document.createElement('li');
		this.left = 0;
		this._play = this.play.bind(this);
		this.element.appendChild(this.bullet);
	}
	Bullet.prototype.play = function() {
		this.left += 4;
		this.bullet.style.left = this.left + 'px';
		if(this.left >= 1000) {
			this.remove();
		}
		else {
			this._timeoutID = setTimeout(this._play, 10);
		}
	};
	Bullet.prototype.remove = function() {
		this.stop();
		this.bullet.remove();
	};
	Bullet.prototype.restart = function() {
		this.stop();
		this.play();
	},
	Bullet.prototype.stop = function() {
		this.left = 0;
		clearTimeout(this._timeoutID);
	};
	return Bullet;
}());



var bullet = new Bullet;
bullet.play();

Rise 09.06.2016 13:19

Bond, да обычный setTimeout почитай как он работает, ещё вариант:
<body>
<style>
@keyframes move {
	100% { left: 500px; background: #777; }
}
.parent, .bullet {
	position: absolute;
	top: 0; left: 0;
	padding: 10px;
	margin: 30px;
	border-radius: 50%;
	background: #eee;
	list-style: none;
	cursor: pointer;
}
.bullet {
	animation: move 2s linear 2 alternate;
}
.bullet:hover {
	animation-play-state: paused;
}
</style>
<script>
var Bullet = (function() {
	function Bullet() {
		var parent = document.createElement('ul');
			parent.classList.add('parent');
			parent.textContent = 'Click';
			parent.addEventListener('click',		this.create.bind(this));
			parent.addEventListener('animationend',	this.remove.bind(this));
			
		var bullet = document.createElement('li');
			bullet.classList.add('bullet');
			bullet.textContent = 'Bullet';
			
		this.parent = document.body.appendChild(parent);
		this.bullet = bullet;
	}
	Bullet.prototype.create = function() {
		var bullet = this.parent.appendChild(this.bullet.cloneNode(true));
	};
	Bullet.prototype.remove = function(event) {
		var bullet = this.parent.removeChild(event.target);
	};
	return Bullet;
}());

var bullet = new Bullet();
</script>
</body>


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