Обзор того, как я использовал макросы для создания анимации в CSS с юлианскими типами.
Введение
Те из вас, кто следит за моими текстами и кодом (спасибо :)), скорее всего, знают, что я работаю над фреймворком для веб-разработки для Джулии под названием Toolips.jl. Причина, по которой я создаю такую вещь, заключается в том, что я верю в Джулию как в потенциальное смягчение или решение языковых проблем, существующих в веб-разработке. Вся методология, лежащая в основе модуля, заключается в том, что все можно сделать с помощью Julia, независимо от того, находится ли он в Javascript, HTML или в другом месте. Идея состоит в том, чтобы создать первый интерфейсный веб-фреймворк Джулии. На самом деле вы можете быть очень удивлены, насколько далеко продвинулся этот проект. Если вы хотите взглянуть на модуль самостоятельно, вы можете взглянуть на него здесь:
Следует отметить, что вы, вероятно, захотите взглянуть на Unstable, там ТОННЫ невыпущенных изменений, некоторые из которых очень опасны. Модуль разбит на несколько компонентов.
- Интерфейс высокого уровня
- Основной сервер
- Расширения сервера
- Servables
Сегодня мы будем работать как над Servables, так и над высокоуровневым интерфейсом, включив анимацию в компоненты стиля в Toolips. Если вы хотите просмотреть этот выпуск на Github, вот ссылка:
Кроме того, обзор всех проблем покажет, насколько мы близки к версии 1.0 Toolips.jl. Излишне говорить, что это супер захватывающе. В любом случае, давайте приступим к созданию этого компонента, так как у меня есть несколько довольно интересных идей, когда дело доходит до его анимации!
Установка в Toolips.jl
Анимацию в Toolips можно сделать одним из двух способов. Во-первых, мы можем применить анимацию к обслуживаемому стилю, чтобы дать анимацию всем компонентам с этим стилем. Второй способ очень похож, за исключением того, что вместо создания класса мы применяем анимацию непосредственно к обслуживаемому объекту, изменяя его свойства. Оба варианта, безусловно, подходят, и, честно говоря, было бы неплохо использовать оба варианта. Давайте взглянем на код, в который это нужно вписать и с которым работать, начиная с конструктора Component.
mutable struct Component <: Servable name::String f::Function properties::Dict
Когда компонент создается, он обычно создается либо с другими компонентами, либо с методом, который напрямую вызывает этот конструктор. Словарь свойств — это действительно единственное, что здесь следует упомянуть, это важно, потому что свойства определяют результат обслуживаемого драматическим образом. Обычно они редактируются с помощью функционального интерфейса. Далее давайте взглянем на конструктор Style, который на самом деле может принимать анимацию в качестве аргумента.
mutable struct Style <: StyleComponent name::String f::Function rules::Dict function Style(name::String; animation::Animation = nothing) .... end end
Подобно полю свойств типа Dict, конструктор Style содержит словарь правил, влияющих на то, что делает стиль. Одно из этих свойств применит анимацию к стилю, и мы сможем сделать это с помощью методов. Однако сначала нам нужно создать конструктор анимации и придумать способ удобной передачи наших анимаций через него. Вот что я придумал, в котором хранятся ключевые кадры, а также другие данные анимации.
mutable struct Animation name::String keyframes::Dict f::Function delay::Float64 length::Float64 function Animation(name::String = "animation"; delay::Float64 = 0.0, length::Float64 = 5.2) f(c) = begin end keyframes::Dict = Dict() new(name, keyframes, f, delay, length) end end
Единственное, чего нам сейчас серьезно не хватает, так это функции f() и какого-то способа добавления ключевых кадров. Вот синтаксис, который нам понадобится для объединения, используя мощь строк.
CSS
@keyframes slidein { from { opacity: 0%; transform: translateY(100%); } to { opacity: 100%; transform: translateY(0%); } }
Во-первых, все начинается с чего-то похожего на макрос Julia, так что может иметь смысл его использовать. Во-вторых, за позициями следуют свойства и изменения этих свойств. Вот макрос, который я придумал, который принимает один из этих ключей ключевого кадра, за которым следует свойство и соответствующее ему значение.
macro keyframe!(anim::Symbol, keyframes::Any ...) anim::Animation = eval(anim) kf = [string(frame) for frame in keyframes] keyframe!(anim, kf) end
Что я настоятельно рекомендую делать при работе с eval() в подобных сценариях, так это аннотировать тип. Таким образом, если то, что мы оцениваем, окажется любым другим типом, кроме этого, оно выдаст ошибку еще до того, как оно будет помещено в стек Джулии. Я подумал, что было бы здорово иметь возможность добавлять свойства немного проще, поэтому push! было отправлено:
import Base: push! push!(anim::Animation, p::Pair) = push!(anim.keyframes, [p[1]] => p[2])
Наконец, я написал метод, связывающий этот ключевой кадр! вызывает в качестве возврата:
function keyframe!(anim::Animation, frames::Vector{String}) prop = string(frames[2]) * ": " value = string(frames[3]) * "; " if string(frames[1]) in keys(anim.keyframes) anim.keyframes[frames[1]] = anim.keyframes[frames[1]] * "$prop $value" else push!(anim.keyframes, frames[1] => "$prop $value") end end
Все это позволяет нам сначала: создать анимацию:
anim = Animation("hello")
затем мы можем анимировать его, используя @keyframe и невероятно простой синтаксис.
@keyframe! anim from height "50px" anim Animation("hello", Dict{Any, Any}("from" => "height: 50px; "), var"#f#34"{String}("hello", Core.Box(Dict{Any, Any}("from" => "height: 50px; "))), 0.0, 5.2)
Мы также можем добавить дополнительные свойства к любому заданному ключевому кадру, например:
@keyframe! anim from width "50px"
Последним компонентом является функция f, которая оборачивает все это в стиль CSS.
mutable struct Animation name::String keyframes::Dict f::Function delay::Float64 length::Float64 function Animation(name::String = "animation"; delay::Float64 = 0.0, length::Float64 = 5.2) f(c) = begin s::String = "<style> @keyframes $name {" for anim in keys(keyframes) vals = keyframes[anim] s = s * "$anim {" * vals * "}" end s * "}</style>" end keyframes::Dict = Dict() new(name, keyframes, f, delay, length) end end
Затем, когда это будет вызвано сервером Toolips, мы получим следующее!
anim.f("h") "<style> hello {from {height: 50px; width: 50px; }}</style>"
Довольно круто, правда?
Воссоздание анимации
В качестве последнего трюка я создам анимацию, а затем попытаюсь использовать ее в таблице HTML. Первым шагом является вызов конструктора анимации:
fadein = Animation("fadein")
Теперь добавим в ключевые кадры от и до.
@keyframe! fadein from opacity "0%" @keyframe! fadein to opacity "100%"
Наконец, для последнего шага мы вызываем f. Здесь я собираюсь вызвать это с помощью «», обычно с Toolips.jl все это будет автоматически и будет сделано сервером с Connection в качестве аргумента. Тем не менее, я хотел поместить это в блокнот, чтобы другие люди могли видеть отображаемую анимацию, если захотят, поэтому, если вы хотите увидеть этот блокнот, вы можете здесь:
В любом случае, давайте вызовем Animation.f():
s = fadein.f("")
Затем я сделаю заголовок, чтобы не импортировать всплывающие подсказки в этот блокнот и тому подобное, я просто напишу его как HTML и установлю стиль анимации.
htm = "<h1 style='animation: fadein 10s;'>Hello there, how are you?</h1>"
Опять же, это то, что обычно обрабатывается сервером и Servables в целом. Обычно свойство «класс» устанавливается после того, как мы применяем стиль в Toolips. Наконец, мы используем display(), чтобы увидеть наше новое творение!
display("text/html", s * htm)
Заключение
Большое спасибо за чтение. Я надеюсь, что эта статья успешно достигла нескольких целей. Во-первых, объяснить сложность и зависимость от типа к типу в этом программном обеспечении простыми словами. Другая цель состояла в том, чтобы продемонстрировать различные методы, которые можно использовать для решения некоторых подобных проблем. Наконец, я также просто хотел дать обновленную информацию о Toolips.jl. Toolips.jl находится на пороге настоящего, ломающего и очень красивого перехода на главную страницу с новыми сервисами, серверными расширениями, стилями и составными компонентами. Как только эта версия 0.1 будет готова, на самом деле появится больше вещей Toolips в виде расширений, что очень интересно! В любом случае, у меня много отличных планов, когда дело доходит до создания веб-сайтов с помощью этого фреймворка, и спасибо, что следите за моим прогрессом! Я взволнован, потому что я действительно думаю, что фреймворк невероятно крут.