Документация Engee

Построение графиков

Genie использует PlotlyJS для создания интерактивных графиков в браузере. В частности, для объявления графиков в коде Julia используются пакет PlotlyJS.jl и его синтаксис.

График PLotlyJS состоит из двух компонентов.

  • Данные: массив объектов трассировки, каждый из которых представляет отдельный набор точек данных и их графическое представление на графике. Объект трассировки определяет тип графика (точечная диаграмма, столбчатая диаграмма, круговая диаграмма, тепловая карта и т. д.) и содержит такие свойства, как цвет, стиль линий или стиль маркера. Объединяя несколько объектов трассировки в массиве данных, можно создавать сложные, многослойные визуализации с различными рядами данных и типами графиков.

using PlotlyBase

trace1 = scatter(
    x=[1, 2, 3, 4],
    y=[10, 15, 13, 17],
    mode="markers",
    name="Trace 1"
)

trace2 = scatter(
    x=[1, 2, 3, 4],
    y=[5, 9, 11, 12],
    mode="lines+markers",
    name="Trace 2",
    line=attr(color="red")
)
  • Макет: определяет общий вид и форматирование графика, включая настройки заголовка графика, меток осей, условных обозначений, полей, цветов фона, линий сетки и т. д.

layout = Layout(
    title="A Scatter Plot with Multiple Traces",
    xaxis=attr(
        title="X Axis Label",
        showgrid=false
    ),
    yaxis=attr(
        title="Y Axis Label",
        showgrid=true,
        range=[0, 20]
    )
)

Чтобы добавить график в приложение Genie, сначала объявите его данные и макет как реактивные переменные:

@out plotdata = [trace1, trace2]
@out plotlayout = layout

и добавьте график в пользовательский интерфейс с помощью малокодового API:

ui() = plot(:plotdata, layout=:plotlayout)

или с помощью тега plotly в коде HTML:

<plotly :data="plotdata" :layout="plotlayout"> </plotly>

Определение графиков из Plots.jl

plotdata также можно получить из графика, определенного с помощью Plots.jl, используя бэкенд Plotly и функции Plots.plotly_traces и Plots.plotly_layout следующим образом:

module App
using GenieFramework
import PlotlyBase, PlotlyKaleido, Plots
Plots.plotly()

p = Plots.plot([1, 2, 3], show=false)
@app begin
    @out traces = Plots.plotly_traces(p)
    @out layout = Plots.plotly_layout(p)
end

function ui()
    plot(:traces, layout=:layout)
end

@page("/", ui)
end

Функция plotly_traces загружается функцией Plots.plotly() в сочетании с PlotlyBase и PlotlyKaleido. Поэтому при вызове Plots.plotly() для plotly_traces пакеты PlotlyBase и PlotlyKaleido должны быть установлены в среде.

Определение графиков на HTML

График можно также полностью определить в коде HTML и просто привязать данные к переменным Julia.

module App
using GenieFramework
@genietools

@app begin
    @out firstX = [1, 2, 3, 4, 5]
    @out firstY = [5, 0, 3, -1, 2]
    @out secondX = [1, 2, 3, 4, 5]
    @out secondY = [1, 4, 6, 4, 4]
end


@page("/", "app.jl.html")
Server.up()
end
<div>
    <plotly
      :data="[
        {
          x: firstX,
          y: firstY,
          mode: 'markers',
          type: 'scatter',
          marker: { color: 'rgb(201, 90, 218)', size: 12 }
        },
        {
          x: secondX,
          y: secondY,
          mode: 'lines+markers',
          type: 'scatter',
          line: { color: 'rgba(61, 185, 100, 0.8)', width: 1.5 },
          marker: { color: 'rgb(61, 185, 100)', size: 8 }
        }
      ]"
      :layout="{
        title: 'Complex StippleJS Plot Example',
        xaxis: { title: 'X Axis', range: [0, 5] },
        yaxis: { title: 'Y Axis', range: [-1, 6] },
        legend: { x: 0.5, y: -0.3, orientation: 'h' }
      }"
    />
  </div>

Обратите внимание, что в этом примере используется пакет JavaScript PlotlyJS, поэтому пакет Julia PlotlyBase не нужен.

Определение событий, связанных с мышью, на графике

PlotlyJS позволяет обнаруживать на графике различные события, связанные с мышью, такие как щелчок, наведение, выбор и перетаскивание. Эти события можно регистрировать для выполнения определенного кода.

Чтобы включить регистрацию событий мыши, необходимо использовать именованный объект ReactiveModel, определенный с помощью @app ModelName. Обратите внимание, что на сегодняшний день именованные модели являются общими для всех сеансов и пользователей, поэтому реакция на любое действие пользователя будет происходить во всех окнах браузера.

Кроме того, код обработки событий связывается с ReactiveModel с помощью макроса @mixin и функции watchplots.

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

module App
using GenieFramework, PlotlyBase, StipplePlotly
@genietools

trace1 = scatter(; x=1:4, y=[0, 2, 3, 5], fill="tozeroy")
trace2 = scatter(; x=1:4, y=[3, 5, 1, 7], fill="tonexty")

@app EventsModel begin
    @out traces = [trace1, trace2]
    @out plotlayout = PlotlyBase.Layout(title="Filled line chart")
    @mixin traces::PlotlyEvents
    @onchange traces_click begin
        @show traces_click
    end
    @onchange traces_hover begin
        @show traces_hover
    end
    @onchange traces_selected begin
        @show traces_selected
    end
    @onchange traces_relayout begin
        @show traces_relayout
    end
end

# начинаем отслеживать графики после загрузки страницы
@mounted EventsModel watchplots()

ui() = [plot(:traces, layout=:plotlayout, syncevents = true)]

route("/") do
    global model
    model = EventsModel |> init |> handlers
    page(model, ui()) |> html
end

Server.isrunning() || Server.up()
end