Оптимизация кода
Написал код падающих букв, аля "Матрица", но код получился очень тяжжелый и жутко лагает. Посоветуйте как оптимизировать. Заранее спасибо.
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); } |
Цитата:
|
Цитата:
т.е. выполнить действие не "прямо сейчас", а положить в очередь событий нуль в некоторых браузерах вызывал ошибку, лучше 1 использовать для таких штук |
Цитата:
|
конечно правильнее его использовать
я говорил про случаи, когда он не поддерживается (старые браузеры) |
С лету две предьявы.
1) Где гребаные коментарии в коде 2) Почему опубликовал кусок JS а не HTML который можно запустить. Я по твоему читая код должен был в воображении увидеть падающие символы ? :) UPD: Блин чувак короче ты шляпу написал :) тут улучшать нечего, ее с нуля писать надо :) Сгенерировать html целиком и вставить его разом вроде бы и прикольно, но вот только движок потратит веcьма порядочно времени на то чтобы распарсить текст и превратить его в элементы dom. И это не считая порядочных затрат ресурсов на генерацию самого этого текста. |
Ну в общем я сильно не заморачивался.
есть три варианта анимации. 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> |
Вот твой код для сравнения
<!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> |
Сегодня только заметил что буковки все разного цвета, а это несколько меняет ситуацию.
Значит строки двигать я не могу ( 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> |
ого! Круто! Всем огромное спасибо, буду разбираться в ответах =)
собственно после того, как увидел первый комментарий решил забить на помощь и сюда не заходил. Пилил гиковское признание в любви девушке, вот что у меня получилось в конце 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> так и не нашел, как добавить кнопку "посмотреть" |
Часовой пояс GMT +3, время: 12:34. |