Добавление движущейся планеты и знакомство с враппером

Теперь нам нужно разместить саму планету вращающуюся вокруг солнца. Для этого мы будем использовать отдельный подшаблон earth.

Добавим подшаблон earth в конец файла :templates/blocks/planet.tmpl

Файл :templates/blocks/planet.tmpl

... //~OPTIONS earth { autoUpdate: true, } //~ARGUMENTS earth { fcfClassInner: "planet-earth-container", fcfStyleInner: fcf.argVal("z-index: @{{args.topPlanet > 0.5 ? 2 : 0}}@"), feq: 60, period: 10, time: 0, pause: false, leftPlanet: fcf.argVal("@{{(Math.sin(Math.PI * args.time / args.period / 1000 * 2) + 1) / 2 * 0.5 + 0.25}}@"), topPlanet: fcf.argVal("@{{(Math.cos(Math.PI * args.time / args.period / 1000 * 2) + 1) / 2 * 0.5 + 0.25}}@"), } //~TEMPLATE earth <div class="planet-earth" style="left: @{{100*args.leftPlanet}}@%; top: @{{100*args.topPlanet}}@%;"></div>

Рассмотрим содержимое добавленного кода.

В самом начале мы устанавливаем опцию autoUpdate равным значению true. Для того, что бы фреймворк автоматически выполнял обновление шаблона при изменении его аргументов.

Теперь перейдем к секции //~ARGUMENTS. Здесь полностью выполняется расчет позиции нашего движущегося объекта по окружности. Аргумент feq задает частоту обновления перерисовки. Аргумент period определяет период вращения объекта в секундах. Позиция планеты рассчитывается аргументами leftPlanet и topPlanet в относительных координатах от 0 до 1, в зависимости от аргумента time, который будет меняться на стороне браузера и хранить в себе время в миллисекундах от начала запуска.

Так же отметим, что мы меняем значение стиля z-index для подшаблона earth. Когда высота объекта меньше 0.5 мы устанавливаем значение z-index равным 0, таким образом мы выполняем эффект скрытия планеты за солнцем. Все это выполняется в расчете параметра fcfStyleInner.

Аргумент pause будет использоваться после, для остановки и воспроизведения анимации.

Теперь выполним рендеринг подшаблона earth в основном шаблоне.

Файл :templates/blocks/planet.tmpl

... //~TEMPLATE <div class="planet-container"> <div class="star-container"> %{{ for(let i = 0; i < args.stars.length; ++i) { }}% <div class="star" style="left:@{{args.stars[i].left}}@%; top: @{{args.stars[i].top}}@%; animation-duration: @{{args.stars[i].duration}}@s; animation-delay: @{{args.stars[i].delay}}@s;"></div> %{{ } }}% </div> <div class="planet-sun-container"> <div class="planet-sun-container-item"> <div class="planet-sun"></div> </div> </div> @{{ render.template("+earth"); }}@ </div> ...

Результат добавления подшаблона earth представлен на картинке

Теперь осталось только запустить счет аргумента time. Для этого создадим файл враппера подшаблона :templates/blocks/planet+earth.tmpl командой или плагинами.

$ cd [PROJECT_DIRECTORY]/templates/blocks $ fcfmngr create wrapper planet+earth

Откройте файл :templates/blocks/planet+earth.wrapper.js и измените его содержимое

Файл :templates/blocks/planet+earth.wrapper.js

fcf.module({ name: "templates/blocks/planet+earth.wrapper.js", dependencies: ["fcf:NClient/Wrapper.js"], module: function(Wrapper){ return class WrapperEx extends Wrapper{ constructor(a_initializeOptions){ super(a_initializeOptions); } async initialize(){ await super.initialize() this.timer(); } timer(){ let self = this; if (!this.getArg("pause")){ let time = (new Date()).getTime(); let diff = this._lastTime ? time - this._lastTime : 1 / this.getArg("feq") * 1000; this.setArg("time", this.getArg("time") + diff); this._lastTime = time; } else { this._lastTime = undefined; } setTimeout(()=>{ self.timer(); }, 1 / this.getArg("feq") * 1000); } }; } });

Собственно сам код враппера очень прост.

Методами getArg и setArg класса fcf.NClient.Wrapper выполняется получение и установка значения аргумента шаблона на стороне браузера.

В методе initialize мы выполняем первый запуск таймера, который увеличивает значение аргумента шаблона time на разницу времени от предыдущего запуска. А аргумент шаблона "pause" просто останавливает обновление шаблона и увеличение аргумента time.