JSFiddle - React, Tailwind, and code Playground
by zjoxic
HTML
<!-- Кнопки -->
<button data-bind="click:toggleAutoMode,text:autoMode()?'Остановить':'Запустить'"></button>
<button data-bind="visible:!autoMode(), click:nextGeneration">Следующее поколение</button>
<button data-bind="click:reset">Сброс</button>
<!-- Игровое поле -->
<div class="field" data-bind="foreach:visibleCells, style:{fontSize:size()+'px'}">
<div class="cell" data-bind="click:toggleAlive, css: {'alive':isAlive}, style: { left:x+'em', top:y+'em' }">
</div>
</div>
CSS
/* Стили */
.field {position: absolute; left:50%; top:50%;}
.cell { width: 1em; height: 1em; position:absolute; box-shadow: inset 0 0 0.2em rgba(0,0,0,0.5); }
.alive {background-color: green;}
JavaScript
/**
* Это модель игрового поля
*/
var model = {
field: {},
generation: 0,
speed: 3,
size: ko.observable(32),
maxFieldWidth: 400,
autoMode: ko.observable(false),
totalAlive: ko.observable(0),
visibleCells: ko.observableArray(),
toToggleCells: {},
//создание новой клетки
createCell: function(x, y){
var cell = new CellModel(x, y);
this.field[x] = this.field[x] || {};
this.field[x][y] = cell;
//магия автоуменьшения поля тут:
var maxCoord = Math.max( Math.abs(x), Math.abs(y) );
if(maxCoord*this.size() > this.maxFieldWidth/2){
this.size(this.maxFieldWidth/2/maxCoord);
}
this.visibleCells.push(cell);
return cell;
},
//получение старой клетки
getCell: function(x, y){
if(x in this.field && y in this.field[x]){
return this.field[x][y];
}
},
//переход к следующему поколению
nextGeneration: function(){
var toToggle = this.toToggleCells;
this.toToggleCells = {};
for(var id in toToggle){
toToggle[id].toggleAlive();
}
if(this.autoMode() && this.totalAlive() === 0){
//если нет живых клеток, ставим на паузу
this.toggleAutoMode();
}
this.generation++;
},
//а это зацикливание программы по таймеру
timerID:null,
toggleAutoMode:function(){
this.autoMode(!this.autoMode());
if(this.autoMode()){
var that = this;
this.timerID = setInterval(function(){that.nextGeneration()}, 1000/this.speed);
}
else{
clearInterval(this.timerID);
}
},
reset: function(){
if(this.autoMode()){
this.toggleAutoMode();
}
this.field = {};
this.toToggleCells = {};
this.visibleCells([]);
this.totalAlive(0);
this.createCell(0, 0).toggleAlive();
this.generation = 0;
...