FuseTools — уникальный инструмент прототипирования и разработки

    И снова доброго времени суток, хабражители. Меня зовут Владимир Миленко, и как вы возможно знаете, я фронтенд-разработчик в компании Иннософт. Возможно вы так-же заметите, что в свободное время я изучаю ситуацию на рынке разработки мобильных приложений. Несколько дней назад я написал статью, в которой описал, что такое NativeScript. Пришло время познакомить вас с другим уникальным инструментом, аналогов которому нет.

    Речь пойдет о FuseTools — фреймворк для написания нативных мобильных приложений с потрясающими возможностями.



    Что же такое FuseTools?


    FuseTools — фреймворк, который предоставляет доступ к OpenGL без необходимости написания кода для него.

    В чем кардинальное отличие от NativeScript, React.Native:

    Fuse работает на уровне OpenGL, предоставляя расширенный доступ к генерации лэйаута. Fuse так же позволяет использовать нативные компоненты, но предоставляет куда более удобный доступ к различным функциям OpenGL.

    Что это дает? Это дает возможность создавать такие анимации, которые вам и не снились, а если и снились — их было очень тяжело привнести в жизнь. Но и не только анимации, в будущем, вы сможете создавать компоненты, и использовать их в своих проектах, но обо всем по порядку.

    Fuse — инструмент не только для прототипирования, но и для разработки. Вы можете писать JS код, который отвечает за логику вашего приложения, но сам UI описывается в декларативном стиле в .ux файлах.

    Сразу перекроем некоторые вопросы, которые могут возникнут:


    Можно ли вызывать нативные методы из Fuse?

    — Да, можно. Для этого используется язык Uno, который позволяет писать код на ObjC/Java, а потом сам компилирует его в тот же нативный код.

    Можно ли использовать NPM-пакеты?

    — Да, можно. Для этого используется сторонняя утилита, которая заставляет компилятор Fuse забирать NPM пакет в бандл.

    Поддерживается ли HotReload?

    — Поддерживается, работает очень быстро.

    Приступим к установке Fuse


    Переходим на fusetools.com и скачиваем установщик для вашей ОС: Mac/Windows. Думаю, про то, как нажимать кнопочку “Я согласен”,”Далее” — не нужно. Мы уже почти готовы к созданию проекта, продолжим:

    В терминале:

    fuse create app habr
    cd habr

    Для ознакомления нам понадобится Sublime Text/Atom/VS Code, для этих редакторов уже есть плагины.

    Для того, чтобы установить sublime плагин:

    fuse install sublime-plugin
    

    Предварительно запустим превью нашего проекта, для этого нужно вызвать контекстное меню на .ux файле и запустить Preview → Local. Открываем нашу папку habr в саблайме и переходим в MainView.ux. В этом файле мы увидим целое приложение, состоящее из тега <App>. Раз уж я говорил об анимации, давайте поставим такую цель:



    Конструирование интерфейса


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

    Опишем базовый лэйаут:

    <App>
    	<ClientPanel>
    	</ClientPanel>
    </App>
    

    Теперь, рассмотрим набор имеющихся примитивов: Rectangle, Circle, Text, Image, Video. Выберем необходимые нам — Rectangle и Circle.

    Перейдем к чуть сложному, созданию собственных шаблонов компонентов. Fuse имеет различные конструкции, которые позволяют описывать ваш лэйаут, воспользуемся конструкцией Class.

    <Rectangle ux:Class="SnapButton" CornerRadius="30" Margin="10" Color=”#5E2E91”>
    </Rectangle>

    Я думаю, здесь все понятно, это шаблон прямоугольника, с отступами со всех сторон по 10 pt, и скруглением углов в 30 pt.

    Разместим инстанс нашего шаблона в ClientPanel. В итоге, наш код будет выглядеть примерно так:

    <App>
    	<ClientPanel>	
    		<SnapButton ux:Name=”loginButton” Width=”300” Height=”60” />
    	</ClientPanel>
    </App>
    

    Добавим внутрь нашего инстанса SnapButton круг:

    <Circle ux:Name="loadingCircle" Width="50%" Height="50%" Opacity="0" StartAngleDegrees="0" LengthAngleDegrees="90">
    	<Stroke Width="2" Brush="#fff" />
    </Circle>

    Из выше описанного кода видно, что наш круг прозрачен и не отображается по умолчанию, также можно заметить, что это не полный круг, а всего-лишь четверть круга. Внутри мы описываем параметр Stroke — обводка, ширина -2, цвет-белый.

    Отлично! Мы готовы приступить к созданию анимации!


    Распишем по шагам:

    1. Превратить кнопку в круг
    2. Проявить наш круг
    3. Запустить анимацию вращения

    Fuse дает нам возможность описывать триггеры, теперь опишем триггер, который будет вызывать анимацию изменения ширины нашей кнопки:

    <WhileTrue ux:Name=”loading”>
    	<Change changeWidth.Value=”true” DelayBack=”0” />
    </WhileTrue>
    <WhileTrue ux:Name=”changeWidth”>
    	<Change loginButton.Width="60" Duration=".5" DurationBack=".5" Easing="CircularInOut"/>
    </WhileTrue>
    

    Из разметки выше видно, что есть два триггера, один с названием loading, управляющий включением триггера changeWidth.

    Триггер ChangeWidth в свою очередь запускает изменение параметра Width у объекта с именем loginButton, длительностью 0.5 секунды в обе стороны.

    Не будем хоть вперед да около, опишем триггер анимации нашего круга:

    <WhileTrue ux:Name="loadCircle">
    			<Change loadingCircle.Opacity="1" Duration="0.3" Delay="0.2" DelayBack="0" DurationBack="0"/>
    			<Spin Target="loadingCircle" Frequency="2"/>
    			<Cycle Target="loadingCircle.LengthAngleDegrees" Low="10" High="300" Frequency="0.7" />
    </WhileTrue>
    

    Здесь мы встречаем Spin и Cycle, первый вращает объект, с заданной частотой, второй же выполняет цикличное изменение параметра с частотой, в нашем случае мы изменяем длину нашей окружности от 10 до 300 в течении 0.7 секунды.

    И последнее — добавим наш новый триггер в триггер loading, после чего вызовем смену значения триггера по событию нажатия на нашу кнопку.

    Вот и все, мы сделали довольно красивую интерактивную кнопку, которая может отображать состояние приложения.

    Финальный код будет выглядеть так:

    <App>
    	<ClientPanel>
    		<SnapButton ux:Name="loginButton" Width="300" Height="60">
    			<Clicked>
    				<Toggle Target="loading"/>
    			</Clicked>
    			<Circle ux:Name="loadingCircle" Width="50%" Height="50%" Opacity="0" StartAngleDegrees="0" LengthAngleDegrees="90">
    				<Stroke Width="2" Brush="#fff" />
    			</Circle>
    		</SnapButton>
    	</ClientPanel>
    	<Rectangle ux:Class="SnapButton" CornerRadius="30" Margin="10" Color="#5E2E91">
    	</Rectangle>
    
    	<WhileTrue ux:Name="loading">
    			<Change changeWidth.Value="true" DelayBack="0"/>
    			<Change loadCircle.Value="true" DelayBack="0"/>
    	</WhileTrue>
    		
    
    	<WhileTrue ux:Name="changeWidth">
    			<Change loginButton.Width="60" Duration=".5" DurationBack=".5" Easing="CircularInOut"/>
    	</WhileTrue>
    
    	<WhileTrue ux:Name="loadCircle">
    			<Change loadingCircle.Opacity="1" Duration="0.3" Delay="0.2" DelayBack="0" DurationBack="0"/>
    			<Spin Target="loadingCircle" Frequency="2"/>
    			<Cycle Target="loadingCircle.LengthAngleDegrees" Low="10" High="300" Frequency="0.7" />
    	</WhileTrue>
    </App>
    

    Стоит заметить, что Fuse поддерживает огромное количество различных параметров для создания анимаций, наложения эффектов, но перейдем дальше.

    Анимации это, конечно, хорошо. Да вот только без логики приложение не напишешь


    Здесь есть несколько вариантов, все они достаточно сырые, что объясняется состоянием Fuse — бета, коммьюнити не такое большое, хотя и готовятся к open-source.

    Можно писать на EcmaScript5, либо в JS файлах, либо внутри разметки. Подключить JS можно добавив тег <JavaScript File=”file.js” />. Фактически, нам дают MVVM и говорят, ну вот как-то так. Немного поплясав, можно добиться интеграции с ES2015 → Babel → ES5. Точно столько же танцев потребуется на интеграцию TS, о чем я подробно описал на форуме fuse.

    Fuse оперирует данными с помощью Observabl’ов, пример использования можно найти по ссылке выше. По умолчанию вам так же доступен Two-Way Binding.

    Вернемся к выполнению нативного кода:

    Fuse использует язык Uno, больше похожий на C#, однако предоставляющий возможность декорировать методы и параметры исполняемыми языками.

    Выглядит это примерно так:

    [Foreign(Language.ObjC)]
            static float GetValue(ObjC.Object handle)
            @{
                ::UISlider* slider = (::UISlider*)handle;
                return [slider value];
            @}
    

    Что мы имеем в итоге?


    Разрабатывать на Fuse что-то серьезное пока-что вряд ли получится, хотя ничего особо не мешает. А вот для создания прототипа, который можно пощупать — на мой взгляд самое то. По обещаниям, Fuse будет представлять возможность экспортировать компоненты для использования в проектах(что, на мой взгляд, прекрасно).

    Ссылки:

    Официальный сайт
    Установка npm-пакетов для приложения
    • +16
    • 17,9k
    • 5
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 5
    • +2
      Стоит дополнительно отметить, весь UI, описанный в .ux файлах, компилируется в c++.
      После чего, с помощью соответствующих тулз, компилируется в нативный код для каждой платформы.
      • +2
        Спасибо за статью! Мощная штука… очень понравилось!
        Менее чем за час установил, накидал простенький прототип и частично добавил код работы с бэкендом из reactnative приложения…
        • 0
          Выглядит интересно, но, к сожалению, пока только под Mac и Windows.
          • 0
            Да, потянулся было скачать, но… Нет под Linux… :(
          • +1
            Почему бы просто не использовать QML? Возможностей на порядок больше, платформ тоже. Да и синтаксис более удобный.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.