27.09.2013, 04:59
|
Новичок на форуме
|
|
Регистрация: 27.09.2013
Сообщений: 3
|
|
Оптимизация кода
Написал код падающих букв, аля "Матрица", но код получился очень тяжжелый и жутко лагает. Посоветуйте как оптимизировать. Заранее спасибо.
function Column (maxlength) {
this.maxlength = maxlength;
this.speed = this.pause = getRandomInt(1, 4);
this.length = getRandomInt(Math.floor(maxlength/2), Math.floor(maxlength/4 + maxlength/2));
this.free_space = getRandomInt(0, Math.floor(maxlength/4));
this.iterator = 0;
this.text = new Array(this.length + this.free_space);
for (var i=0; i < this.text.length; i++) {
if (i < this.length) {
this.text[i] = String.fromCharCode(getRandomInt(97,122));
} else {
this.text[i] = '.';
}
}
this.length += this.free_space;
}
Column.prototype.inPause = function () {
var result = true;
this.pause--;
if (this.pause == 0) {
this.pause = this.speed;
result = false;
}
return result;
}
Column.prototype.needNew = function() {
result = false;
if (this.iterator == this.text.length + this.maxlength) {
result = true;
}
return result;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function show(columns, array) {
var result = '';
for (var i=0; i < columns.length; i++) {
if (!columns[i].inPause()) {
columns[i].iterator++;
for (var j=0; j < columns[i].iterator; j++){
if (columns[i].iterator - (j + 1) < array.length) {
if (columns[i].length - (j + 1) >= 0) {
array[columns[i].iterator - (j + 1)][i] = columns[i].text[columns[i].length - (j + 1)];
} else {
array[columns[i].iterator - (j + 1)][i] = '.';
}
}
}
if (columns[i].needNew()) {
columns[i] = new Column(array.length);
};
}
}
for (var i=0; i < heigth_length; i++) {
for (var j=0; j < width_length; j++) {
if (array[i][j]=='.') {
result += '<font color="#000000">' + array[i][j] + '</font>';
} else if (i < heigth_length-1) {
if (array[i+1][j]=='.') {
result += '<font color="#00FF00">' + array[i][j] + '</font>';
} else {
result += '<font color="#00CC00">' + array[i][j] + '</font>';
}
}
}
result += '</br>';
}
elem.innerHTML = result;
}
{
var elem = document.getElementById('matrix');
elem.style.backgroundColor = "#000";
elem.style.fontFamily = "Courier New";
elem.style.fontSize = "16px";
var width_length = Math.floor(elem.offsetWidth/10);
var heigth_length = Math.floor(elem.offsetHeight/10);
var columns = new Array(width_length);
for (var i=0; i < width_length; i++) {
columns[i] = new Column(heigth_length);
}
var array = new Array(heigth_length);
for (var i=0; i < heigth_length; i++) {
array[i] = new Array();
for(var j=0; j < width_length; j++) {
array[i][j] = '.';
}
}
var timer = setInterval(function() { show(columns,array) }, 0);
}
|
|
27.09.2013, 06:19
|
|
Профессор
|
|
Регистрация: 11.09.2010
Сообщений: 8,804
|
|
Сообщение от Dpakowa
|
var timer = setInterval(function() { show(columns,array) }, 0);
|
Нулевой интервал. Это как вобще? Для анимации нужно использовать requestAnimationFrame
__________________
В личку только с интересными предложениями
|
|
27.09.2013, 17:43
|
Профессор
|
|
Регистрация: 12.04.2010
Сообщений: 557
|
|
Сообщение от danik.js
|
Нулевой интервал. Это как вобще?
|
это как process.nextTick в node
т.е. выполнить действие не "прямо сейчас", а положить в очередь событий
нуль в некоторых браузерах вызывал ошибку, лучше 1 использовать для таких штук
|
|
27.09.2013, 19:40
|
|
Профессор
|
|
Регистрация: 11.09.2010
Сообщений: 8,804
|
|
Сообщение от Яростный Меч
|
нуль в некоторых браузерах вызывал ошибку, лучше 1 использовать для таких штук
|
А почему не animationFrame?
__________________
В личку только с интересными предложениями
|
|
27.09.2013, 20:52
|
Профессор
|
|
Регистрация: 12.04.2010
Сообщений: 557
|
|
конечно правильнее его использовать
я говорил про случаи, когда он не поддерживается (старые браузеры)
|
|
29.09.2013, 00:00
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
С лету две предьявы.
1) Где гребаные коментарии в коде
2) Почему опубликовал кусок JS а не HTML который можно запустить. Я по твоему читая код должен был в воображении увидеть падающие символы ?
UPD: Блин чувак короче ты шляпу написал тут улучшать нечего, ее с нуля писать надо Сгенерировать html целиком и вставить его разом вроде бы и прикольно, но вот только движок потратит веcьма порядочно времени на то чтобы распарсить текст и превратить его в элементы dom. И это не считая порядочных затрат ресурсов на генерацию самого этого текста.
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 29.09.2013 в 19:04.
|
|
29.09.2013, 01:46
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
Ну в общем я сильно не заморачивался.
есть три варианта анимации.
1) Возможно самый быстрый это заранее готовить div столбец а потом двигать его целиком.
2) просто тупо добавлять в столбец по символу
3) Третий химичить с массивами символов, вероятно самый тормозной. (то есть анимировать каждый символ в отдельности )
4)upd Либо пихать текст в innerHtml
Пример реализации добавления по символу (2й вариант).
+ Обрати внимание на несколько вещей,
1) счетчик оставшихся кадров управляет логикой работы линии, при>12 кадров он добавляет символы, при <12 добавляет пробелы, а при нуле обнуляет строку и генерит новые параметры.
2) Я создал сцену на которой есть действующие лица (столбцы). Прикол в том что на сцену я могу добавлять не только линии, но и все что захочу и это тоже будет анимироваться. То есть я отделил сцену от действующих лиц тем самым позволив наполнять сцену нашего маленького театра разнотипными персонажами.
3) Ты по моему на паузу ставишь еще линии, я это не делал. Но если нужно то можно решить устанавливая тригер холостого хода в true и генерируя счетчик кадров, тригер будет вставать обратно в false при достижении счетчиком кадров нуля. Пока тригер true никакой анимации не происходит естественно.
<!DOCTYPE HTML>
<html>
<head>
<style>
.textline{
color:green;
width: 3%;
height:300px;
overflow:hidden;
text-align: center;
font: Consolas, Monaco, monospac;
font-size:20px;
float:left;
}
</style>
</head>
<body style="height:100%;background:black;">
<div id="stage"></div>
<script>
//Генератор случайных чисел
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max-min) ) + min;
}
//сцена на которой происходит анимация
function Stage(el){
//Действующие лица анимации
var children=[];
//добавляет новых актеров на сцену
this.add=function(line){
children.push(line);
el.appendChild(line.el);
}
//обновляет состояние актеров на сцене
this.update=function(time){
for (var i=0;i<children.length;i++){
children[i].update(time);
}
}
}
//Действующие лица анимации
function Line(){
var frameLength=getRandomInt(10,50),
oldTime=0,
interval=getRandomInt(10,400);
this.el=document.createElement('div');
this.el.classList.add('textline')
//обновляем линию
this.update=function(time){
var sym="";
if (time-oldTime>interval){ //скорость
//счетчик кадров
frameLength--;
if (frameLength>12){ //если больше 12 кадров добавим симво
sym=String.fromCharCode(getRandomInt(97,122));
this.el.innerText=sym+"\n"+this.el.innerText;
} else if(frameLength==0) { //если 0 кадров делаем сброс
this.el.innerText="";
frameLength=getRandomInt(10,50); //сгенерируем новую длинну
interval=getRandomInt(10,400); //сгенерируем новую скорость
} else { //если меньше 12 кадров то фигачим пробелы
this.el.innerText=" \n"+this.el.innerText;
}
oldTime=time;
}
}
}
//Счетчик кадров
function FPS(){
var oldTime='0',
count=0,
sec=0;
this.el=document.createElement('div');
this.el.style.color="#777";
this.el.innerText="0";
this.update=function(time){
//new Date медленная операция, как альтернативу можно юзать переменную time но точность измерения будет ниже
sec=new Date().getSeconds();
if (sec!=oldTime){
this.el.innerText='FPS='+count;
oldTime=sec;
count=0;
}
count++;
}
}
//=========== инициализация приложения ================//
var stage=new Stage(document.getElementById('stage') );
for (var i=0;i<33;i++){
stage.add( new Line() );
}
stage.add( new FPS() );
+function animloop(time){
stage.update(time);
requestAnimationFrame(animloop);
}(0);
</script>
</body>
</html>
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 29.09.2013 в 22:10.
|
|
29.09.2013, 02:01
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
Вот твой код для сравнения
<!DOCTYPE HTML>
<html>
<head> </head>
<body style="width:100%;height:400px;">
<div id="matrix" style="width:100%;height:100%;" > </div>
<script>
function Column (maxlength) {
this.maxlength = maxlength;
this.speed = this.pause = getRandomInt(1, 4);
this.length = getRandomInt(Math.floor(maxlength/2), Math.floor(maxlength/4 + maxlength/2));
this.free_space = getRandomInt(0, Math.floor(maxlength/4));
this.iterator = 0;
this.text = new Array(this.length + this.free_space);
for (var i=0; i < this.text.length; i++) {
if (i < this.length) {
this.text[i] = String.fromCharCode(getRandomInt(97,122));
} else {
this.text[i] = '.';
}
}
this.length += this.free_space;
}
Column.prototype.inPause = function () {
var result = true;
this.pause--;
if (this.pause == 0) {
this.pause = this.speed;
result = false;
}
return result;
}
Column.prototype.needNew = function() {
result = false;
if (this.iterator == this.text.length + this.maxlength) {
result = true;
}
return result;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function show(columns, array) {
var result = '';
for (var i=0; i < columns.length; i++) {
if (!columns[i].inPause()) {
columns[i].iterator++;
for (var j=0; j < columns[i].iterator; j++){
if (columns[i].iterator - (j + 1) < array.length) {
if (columns[i].length - (j + 1) >= 0) {
array[columns[i].iterator - (j + 1)][i] = columns[i].text[columns[i].length - (j + 1)];
} else {
array[columns[i].iterator - (j + 1)][i] = '.';
}
}
}
if (columns[i].needNew()) {
columns[i] = new Column(array.length);
};
}
}
for (var i=0; i < heigth_length; i++) {
for (var j=0; j < width_length; j++) {
if (array[i][j]=='.') {
result += '<font color="#000000">' + array[i][j] + '</font>';
} else if (i < heigth_length-1) {
if (array[i+1][j]=='.') {
result += '<font color="#00FF00">' + array[i][j] + '</font>';
} else {
result += '<font color="#00CC00">' + array[i][j] + '</font>';
}
}
}
result += '</br>';
}
elem.innerHTML = result;
}
{
var elem = document.getElementById('matrix');
elem.style.backgroundColor = "#000";
elem.style.fontFamily = "Courier New";
elem.style.fontSize = "16px";
var width_length = Math.floor(elem.offsetWidth/10);
var heigth_length = Math.floor(elem.offsetHeight/10);
var columns = new Array(width_length);
for (var i=0; i < width_length; i++) {
columns[i] = new Column(heigth_length);
}
var array = new Array(heigth_length);
for (var i=0; i < heigth_length; i++) {
array[i] = new Array();
for(var j=0; j < width_length; j++) {
array[i][j] = '.';
}
}
console.log(array);
var timer = setInterval(function() { show(columns,array) }, 1);
}
</script>
</body>
</html>
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
|
|
29.09.2013, 15:30
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
Сегодня только заметил что буковки все разного цвета, а это несколько меняет ситуацию.
Значит строки двигать я не могу ( innerHTML юзать западло ). Окей тогда попробуем сгенеририть контейнеры для символов для каждой строки. Мы будем перебирать контейнеры снизу вверх и копировать значение в текущий контейнер из вышестоящего. Затем нам останется просто добавить новый символ в самый верхний контейнер. Помимо символа я могу скопировать с верхнего контейнера и любые свойства (к примеру цвет).
Кстатии когда столбец заполне не полностью можно немного похимичить и избавится от лишнего копирования, это как идея.
На ноуте с производительность муть какая то, обычно выдает 60fps, но иногда 15 fps. Не в первом скрипте подмечаю сильные колебания в скорости с причинами не зависящими от скрипта.
<!DOCTYPE HTML>
<html>
<head>
<style>
.textline{
color:green;
width: 3%;
height:300px;
overflow:hidden;
text-align: center;
font: Consolas, Monaco, monospac;
font-size:20px;
float:left;
}
</style>
</head>
<body style="height:100%;background:black;">
<div id="stage"></div>
<script>
//Генератор случайных чисел
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max-min) ) + min;
}
//сцена на которой происходит анимация
function Stage(el){
//Действующие лица анимации
var children=[];
//добавляет новых актеров на сцену
this.add=function(line){
children.push(line);
el.appendChild(line.el);
}
//обновляет состояние актеров на сцене
this.update=function(time){
for (var i=0;i<children.length;i++){
children[i].update(time);
}
}
}
//Действующие лица анимации
function Line(){
var frameLength=getRandomInt(10,50),
oldTime=0,
interval=getRandomInt(10,400);
this.el=document.createElement('div');
this.el.classList.add('textline')
//сгенерируем контейнеры в которые будем помещать буковки
for (var i=0;i<12;i++){
this.el.appendChild( document.createElement('div') );
}
var children=this.el.children;
//обновляем линию
this.update=function(time){
var sym="",
count=11;
if (time-oldTime>interval){ //анимируется только если временной промежуток больше интервала
//счетчик кадров
frameLength--;
//Сместим старые элементы вниз
while( count-- && count>0){
children[count].innerText=children[count-1].innerText;
children[count].style.color=children[count-1].style.color
}
//Добавим новые
if (frameLength>12){ //если больше 12 кадров добавим символ
sym=String.fromCharCode(getRandomInt(97,122));
children[0].innerText=sym;
children[0].style.color="rgb(0,"+getRandomInt(90,255)+",0)";
} else if(frameLength==0){
frameLength=getRandomInt(10,50); //сгенерируем новую длинну
interval=getRandomInt(10,400); //сгенерируем новую скорость
} else { //если меньше 12 кадров то фигачим \n
children[0].innerText='\n';
}
oldTime=time;
}
}
}
//Счетчик кадров
function FPS(){
var oldTime='0',
count=0,
sec=0;
this.el=document.createElement('div');
this.el.style.color="#777";
this.el.innerText="0";
this.update=function(time){
//new Date медленная операция, как альтернативу можно юзать переменную time но точность измерения будет ниже
sec=new Date().getSeconds();
if (sec!=oldTime){
this.el.innerText='FPS='+count;
oldTime=sec;
count=0;
}
count++;
}
}
//=========== инициализация приложения ================//
var stage=new Stage(document.getElementById('stage') );
for (var i=0;i<33;i++){
stage.add( new Line() );
}
stage.add( new FPS() );
+function animloop(time){
stage.update(time);
requestAnimationFrame(animloop);
}(0);
</script>
</body>
</html>
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 29.09.2013 в 22:33.
|
|
29.09.2013, 21:22
|
Новичок на форуме
|
|
Регистрация: 27.09.2013
Сообщений: 3
|
|
ого! Круто! Всем огромное спасибо, буду разбираться в ответах =)
собственно после того, как увидел первый комментарий решил забить на помощь и сюда не заходил. Пилил гиковское признание в любви девушке, вот что у меня получилось в конце http://forsaad.ruskyhosting.ru/
Теперь засяду переделывать =)
Ну и для тех, кому не хочется переходить по ссылке:
<!DOCTYPE HTML>
<head>
<style>
#matrix {
height:100%;
width:100%;
top:0;
left:0;
position:absolute;
background-color:#000;
color:#00aa00;
font-family:Courier New;
overflow:hidden;
line-height:10px;
}
</style>
</head>
<body>
<div id="matrix">
.
</div>
</body>
<script type="text/javascript">
function Column (maxlength) {
this.maxlength = maxlength;
this.speed = this.pause = getRandomInt(1, 5);
this.length = getRandomInt(Math.floor(maxlength/2), Math.floor(maxlength/4 + maxlength/2));
this.free_space = getRandomInt(0, Math.floor(maxlength/4));
this.iterator = 0;
//хардкод Start
this.stoped = false;
//END
this.text = new Array(this.length + this.free_space);
for (var i=0; i < this.text.length; i++) {
if (i < this.length) {
this.text[i] = String.fromCharCode(getRandomInt(65,90));
} else {
this.text[i] = " ";
}
}
this.length += this.free_space;
}
Column.prototype.inPause = function () {
var result = true;
//хардкод Start
if (!this.stoped) {
//END
this.pause--;
if (this.pause == 0) {
this.pause = this.speed;
result = false;
}
}
return result;
}
Column.prototype.needNew = function() {
result = false;
if (this.iterator == this.text.length + this.maxlength) {
result = true;
}
return result;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function show() {
var result = '';
stop_this--;
for (var i=0; i < columns.length; i++) {
if (!columns[i].inPause()) {
columns[i].iterator++;
for (var j=0; j < columns[i].iterator; j++) {
if (columns[i].iterator - (j + 1) < array.length) {
if (columns[i].length - (j + 1) >= 0) {
array[columns[i].iterator - (j + 1)][i] = columns[i].text[columns[i].length - (j + 1)];
} else {
array[columns[i].iterator - (j + 1)][i] = " ";
}
//впадло гемороится, хардкод для любимой
var my_text_array = [ ' ', ' ', 'S', 'A', 'A', 'D', ' ', ' ', 'I', 'C', 'H', ' ', 'L', 'I', 'E', 'B', 'E', ' ', 'D', 'I', 'C', 'H', ' ', ' '];
if (stop_this<=0) {
if (columns[i].iterator - (j + 1) == Math.floor(array.length/2)) {
if (i > (Math.floor(array[0].length/2) - 13)) {
if (i < (Math.floor(array[0].length/2) + 12)) {
if (array[columns[i].iterator - (j + 1)][i] == my_text_array[i - Math.floor(array[0].length/2) + 12]) {
columns[i].stoped = true;
}}}}}
//END hardcode
}
}
if (columns[i].needNew()) {
columns[i] = new Column(array.length);
}
}
}
for (var i=0; i < array.length; i++) {
for (var j=0; j < array[i].length; j++) {
if (array[i][j]==" ") {
result += array[i][j];
} else if (i < array.length-1) {
if (i == Math.floor(array.length/2) && j>(Math.floor(array[0].length/2) - 13) && j<(Math.floor(array[0].length/2) + 12)){
result += '<font color="#FFFFFF">' + array[i][j] + '</font>';
} else if (array[i+1][j]==" ") {
// result += '<font color="#40FF00">' + array[i][j] + '</font>';
result += array[i][j];
} else {
result += array[i][j];
}
}
}
result += '</br>';
}
elem.innerHTML = result;
}
function stop_start() {
var elem = document.getElementById('stop');
if (stop) {
elem.value='Старт';
timer = function() {};
stop = false;
} else {
elem.value='Стоп';
timer = function() {
requestAnimationFrame(timer);
show();
}
timer();
stop = true;
}
}
{
var elem = document.getElementById('matrix');
var width_length = Math.floor(elem.offsetWidth/10)+1;
var heigth_length = Math.floor(elem.offsetHeight/10)+2;
stop_this = heigth_length*4;
var columns = new Array(width_length);
for (var i=0; i < width_length; i++) {
columns[i] = new Column(heigth_length);
}
var array = new Array(heigth_length);
for (var i=0; i < heigth_length; i++) {
array[i] = new Array();
for(var j=0; j < width_length; j++) {
array[i][j] = " ";
}
}
var stop = true;
timer = function() {
requestAnimationFrame(timer);
show();
}
timer();
}
</script>
</html>
так и не нашел, как добавить кнопку "посмотреть"
|
|
|
|