Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Оптимизация кода (https://javascript.ru/forum/project/41734-optimizaciya-koda.html)

Dpakowa 27.09.2013 04:59

Оптимизация кода
 
Написал код падающих букв, аля "Матрица", но код получился очень тяжжелый и жутко лагает. Посоветуйте как оптимизировать. Заранее спасибо.
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);

}

danik.js 27.09.2013 06:19

Цитата:

Сообщение от Dpakowa
var timer = setInterval(function() { show(columns,array) }, 0);

Нулевой интервал. Это как вобще? Для анимации нужно использовать requestAnimationFrame

Яростный Меч 27.09.2013 17:43

Цитата:

Сообщение от danik.js
Нулевой интервал. Это как вобще?

это как process.nextTick в node
т.е. выполнить действие не "прямо сейчас", а положить в очередь событий
нуль в некоторых браузерах вызывал ошибку, лучше 1 использовать для таких штук

danik.js 27.09.2013 19:40

Цитата:

Сообщение от Яростный Меч
нуль в некоторых браузерах вызывал ошибку, лучше 1 использовать для таких штук

А почему не animationFrame?

Яростный Меч 27.09.2013 20:52

конечно правильнее его использовать

я говорил про случаи, когда он не поддерживается (старые браузеры)

DjDiablo 29.09.2013 00:00

С лету две предьявы.
1) Где гребаные коментарии в коде
2) Почему опубликовал кусок JS а не HTML который можно запустить. Я по твоему читая код должен был в воображении увидеть падающие символы ? :)

UPD: Блин чувак короче ты шляпу написал :) тут улучшать нечего, ее с нуля писать надо :) Сгенерировать html целиком и вставить его разом вроде бы и прикольно, но вот только движок потратит веcьма порядочно времени на то чтобы распарсить текст и превратить его в элементы dom. И это не считая порядочных затрат ресурсов на генерацию самого этого текста.

DjDiablo 29.09.2013 01:46

Ну в общем я сильно не заморачивался.

есть три варианта анимации.
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 02:01

Вот твой код для сравнения

<!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>

DjDiablo 29.09.2013 15:30

Сегодня только заметил что буковки все разного цвета, а это несколько меняет ситуацию.

Значит строки двигать я не могу ( 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>

Dpakowa 29.09.2013 21:22

ого! Круто! Всем огромное спасибо, буду разбираться в ответах =)
собственно после того, как увидел первый комментарий решил забить на помощь и сюда не заходил. Пилил гиковское признание в любви девушке, вот что у меня получилось в конце 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] = "&nbsp;";
		}
	}
	
	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] = "&nbsp;";
					
					}
					//впадло гемороится, хардкод для любимой
					var my_text_array = [  '&nbsp;', '&nbsp;', 'S', 'A', 'A', 'D', '&nbsp;', '&nbsp;', 'I', 'C', 'H', '&nbsp;', 'L', 'I', 'E', 'B', 'E', '&nbsp;', 'D', 'I', 'C', 'H',  '&nbsp;', '&nbsp;'];
		
					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]=="&nbsp;") {
				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]=="&nbsp;") {
//					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] = "&nbsp;";
	}
}

var stop = true;

timer = function() {
   requestAnimationFrame(timer);
   show(); 
}

timer();

}


</script>

</html>


так и не нашел, как добавить кнопку "посмотреть"

рони 29.09.2013 21:32

Цитата:

Сообщение от Dpakowa
как добавить кнопку "посмотреть"

run в тег
[HTML  run]

DjDiablo 29.09.2013 22:09

Не стоит копировать с ответов часть ответственную за взаимодействие с DOM. 2е решение хоть и красивое но FullScreen по производительности не потянет 100X30 это 3000 операций с дум на кадр. А это очень много. При таких масштабах нужно обращаться к дум как можно меньше,а это означает что придется юзать либо innerHTML/innerText, либо Fragment. 2й пример пожалуй неудачный, а нападка на innerHtml в первом комменте чересчур предвзята.

1Й основан на innerText и он на фуллскрине выдает 30 кадров. Только slice для строки пришлось добавить.

DjDiablo 30.09.2013 04:40

Всетаки не оставили меня мысли об этой сраной матрице. Выкрал еще чуток времени и сделал набросок под один innerHtml.
Все намного проще вышло чем мне показалось с первого раза.

>Stage теперь не нужен так как нет больше столбиков анимируемых отдельно
>Формирование строки для innerHTML и скроллинг массива происходит одновременно, за один и тот же перебор.

Теперь с Fragment надо еще по попробывать, дабы скролить сложные HTML элементы :)

<body style="height:100%;background:black;">
    <div id="matrix" style="width:100%;height:100%; font-family:Courier New;color:green;"></div>
</body>

<script>
    function getRandomInt(min, max) {
	    return Math.floor(Math.random() * (max-min) ) + min;
    }

	//Класс управлюящий поведением колонок
	function Column(minSize){

      //сбрасывает столбик
      this.reset=function(){
        this.frameCount=1;                     //счетчик пропущенных кадров
        this.speed=getRandomInt(1,5);          //количество пропущенных кадров на один сработавший
        this.length=getRandomInt(minSize,minSize+15); //длинна падающего столбца
      }

      //уменьшает счетчик на единицу
      this.ReduceThecounter=function(){      
        if ( (this.frameCount--) <0) {            //уменьшаем счетчик кадров, если длинна<0 то выполним фрагмент кода
          this.frameCount=this.speed;            
          if ( ( this.length--) <0) this.reset();  //уменьшаем длинну столбца, если длинна<0 то сбрасываем столбец
        }
      }

      this.reset();
    }

	//Матрица
	function Matrix(elem,sizeX,sizeY){
      var columns=[],
          elem= typeof elem=="string"?document.getElementById(elem):elem,
          matrix=[];

	  //Инициализация колонок и первоначальное заполнение матрицы
	  for (var x=0;x<sizeX;x++){
        columns.push(new Column(sizeY+1) );
        matrix.push([]);
        for (var y=0;y<sizeY;y++) {
          matrix[x][y]={sym:"&nbsp"};
        }		
      }

     //метод обновления
     this.update=function(){
        var y=sizeY,
            x=0,
            result="";

        while(y--){
          x=sizeX; 
          while(x--){
            if (y==0) columns[x].ReduceThecounter();
            if(columns[x].frameCount==0){
              if (y==0){ 			
	            matrix[x][0].sym= (columns[x].length>sizeY)?String.fromCharCode( getRandomInt(97,122) ):"&nbsp";
	          } else {
	            matrix[x][y].sym=matrix[x][y-1].sym;	
	          }      
            }
            result=matrix[x][y].sym+result;	    
          }                     			
          result="<br/>"+result;
        }
		elem.innerHTML=result;
	  }
    }

	var m=new Matrix('matrix',82,17);
	+function f(){
      m.update();
      setTimeout(f,1)//setTimeut для демки производительности оставил
	}();
</script>

danik.js 30.09.2013 05:29

Дык а нафига вообще тут DOM использовать? Есть же уже куча готовых реализаций на canvas
http://tenthpla.net/matrix/
http://warwolf.org/404

DjDiablo 30.09.2013 05:47

Цитата:

Сообщение от danik.js (Сообщение 274316)
Дык а нафига вообще тут DOM использовать? Есть же уже куча готовых реализаций на canvas
http://tenthpla.net/matrix/
http://warwolf.org/404

А это не мои проблемы :) Мне таки именно dom помучить хотелось :)

А автору темы надо при помощи МАТРИЦЫ признаться в любви на НЕМЕЦКОМ ЯЗЫКЕ !!!
Воистину любовь толкает на безрассудные поступки :D

Deff 30.09.2013 05:57

Не оч симпатично - буквы падают линейно и синхронно, а реале вертикальные строки двигались с чуть разной скоростью меняющейся туды сюды - похожей на дождь.
Проще заготовить рандомно заполненные буквами вертикальные div, уже вставленные в единый блок ( во всю ширину экрана и высотой - в полтора - два экрана) и этот блок двигать с постоянной скоростью, а вертикальные div в нём(они не прозрачные, а с черным фоном) - рандомно- тудем - сюдем(вверх-вниз) с мелкой скоростью. При близости окончания верхнего обреза текущего блока, сверху, с перекрытием, - накладывать дубликат текущего блока(который во всю ширину)(т.е это будет второй повтор анимации) В принципе, если скорость позволит, то пока идет первый заход, можно сгенерить и совершенно новый второй общий блок

DjDiablo 30.09.2013 14:15

DEFF
Они не синхронно падают, у примера выше просто разброс в скорости небольшой от 1 до 5, и длительность колонок большая была и это все очень быстро в придачу.

Можно поиграться с кастомизацией здесь http://learn.javascript.ru/play/0a6oXb

Поиграться со скоростью (speed это количество пропущенных кадров на один сработавший)
к примеру this.speed=getRandomInt(0,4)*3;
0 минимальная
4 максимальная
3 это множитель делающий разброс в скорости более выраженным

поиграться с длинной колонок
к примеру this.length=getRandomInt(minSize,minSize+15)
minSize означает что длинна минимум равна высоте экрана
minSize+15 означает что можно генерировать столбик до 15 символов
Подмечу что minSize для столбика это количество пробелов разделяющих столбики, и естественно оно равно высоте экрана (иначе столбец исчезнет раньше чем скроется внизу за экраном).

У меня чисто академический интерес связанный с быстрым падением большой кучи буковок с разной скоростью :) Красота лично мне мало интересна :) Заранее подготовленные столбики двигать не пробывал, их штук 130 будет.

DjDiablo 03.10.2013 00:20

Я эксперементировал с typeScript и в порядке эксперемента переписал на нем код из примера выше. Публикую просто для сравнения, дабы мой скорбный труд не пропал совсем даром :)
Производительность ебстебственно одинаковая.

var getRandomInt=(min:number, max:number)=> Math.floor(Math.random() * (max - min)) + min;

//Класс управляющий поведением колонок
class Column {
    frameCount:number;//счетчик пропущенных кадров (тип число)
    length:number;    //Длина анимации (тип число)
    speed:number;     //это значение устанавливается frameCount, если он ниже нуля (тип число)

    //конструктор. Прикольно что minSize сразу в this попадает :)
    constructor(private minSize:number) {
        this.reset();
    }
    
    //сбрасывает столбик
    public reset() {
        this.frameCount = 1;
        this.speed = getRandomInt(1, 5);
        this.length = getRandomInt(this.minSize, this.minSize + 15);
    }

    //уменьшает счетчик на единицу
    public ReduceThecounter() {
        if ( ( this.frameCount-- ) < 0) {
            this.frameCount = this.speed;
            if ( (this.length--) < 0) this.reset();
        }
    }
}

//Матрица
class Matrix {
    private columns=[];
    private matrix=[];

    constructor(private elem, private sizeX:number, private sizeY:number){
        this.elem=typeof elem == "string" ? document.getElementById(elem) : elem;//не стал мудрить, оставил в стиле JS
        for (var x = 0; x < sizeX; x++) {
            this.columns.push(new Column(sizeY + 1));
            this.matrix.push([]);
            for (var y = 0; y < sizeY; y++) {
                this.matrix[x][y] = { sym: "&nbsp" };
            }
        }
    }

    //метод обновления
     public update () {
        var y = this.sizeY,
            x = 0,
            result = "";

        while (y--) {
            x = this.sizeX;
            while (x--) {
                if (y == 0) this.columns[x].ReduceThecounter();
                if (this.columns[x].frameCount == 0) {
                    if (y == 0) {
                        this.matrix[x][0].sym = (this.columns[x].length > this.sizeY) ? String.fromCharCode(getRandomInt(97, 122)) : "&nbsp";
                    } else {
                        this.matrix[x][y].sym = this.matrix[x][y - 1].sym;
                    }
                }
                result = this.matrix[x][y].sym + result;
            }
            result = "<br/>" + result;
        }
        this.elem.innerHTML = result;
    }
}
var m = new Matrix('matrix', 82, 17);

+(function f() {
    m.update();
    setTimeout(f, 1);
})();
//# sourceMappingURL=app.js.map


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