# Adding a play button to a PlotlyJS plot

**URL:** <https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383>\
**Category:** Visualization\
**Tags:** plotlyjs\
**Created:** [March 1, 2023, 11:24am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383 "2023-03-01T11:24:16Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![phiG](https://avatars.discourse-cdn.com/v4/letter/p/96bed5/32.png) [@phiG](https://discourse.julialang.org/u/phiG)\
**Post date:** [March 1, 2023, 11:24am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/1 "2023-03-01T11:24:16Z")

</div>

Hi everyone,

since I got a perfect answer last time on [how to add sliders to a Plotly Plot in the first place](https://discourse.julialang.org/t/plotly-add-slider-to-vector-of-heatmaps/93211), this time I would be delighted if someone could help me edit the code below such that there is a Play Button in the Plot that automatically iterates through the different subplots (randomly generated matrices displayed as heatmaps in this case).

I know this is theoretically possible with the ‘updatemenus’ attribute but I cannot find out how to do this from the documentation provided by Plotly.

Thank you very much!

```julia
using PlotlyJS

Matrices = [rand(2,2) for i = 1 : 3]
colorscale = [[0, "white"], [1, "cyan"]]

maps = Plot( heatmap(z=Matrices[1], colorscale=colorscale),
              Layout(
                     width=400, 
                     height=400, 
                     margin_b=90,  
                     #this section creates the slider in the plot which can be dragged, but only manually
                     sliders= [
                            attr(
                                   active=0, 
                                   pad_t=20, 
                                   steps=[
                                          attr(
                                                 method = "restyle", 
                                                 label= "Heatmap $k",
                                                 args = [
                                                        attr(
                                                               z= (Matrices[k], ), 
                                                               colorscale=(colorscale, )
                                                        )
                                                 ] 
                                          ) for k= 1:length(Matrices)] #end steps vector
                            ) #end slider attributes
                     ] #end sliders
              ) #end layout
       ) #end plot
  
display(maps)

```

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 3, 2023, 12:01pm UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/2 "2023-03-03T12:01:08Z")

</div>

Until you receive a more involved response, you may be able to adapt this example from the JS version: [Filled-area animation in JavaScript](https://plotly.com/javascript/filled-area-animation/#multiple-trace-filled-area)

---

<div class="post-metadata">

**Author:** ![phiG](https://avatars.discourse-cdn.com/v4/letter/p/96bed5/32.png) [@phiG](https://discourse.julialang.org/u/phiG)\
**Post date:** [March 19, 2023, 2:04pm UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/3 "2023-03-19T14:04:51Z")

</div>

Thanks for the link, [I have now tried many ideas but the only thing I get to work is the play button showing up in the plot](https://community.plotly.com/t/adding-an-animation-button-to-a-julia-plot-with-slider/73404). However it still does nothing when I click it.  
In the meantime I found [this](https://discourse.julialang.org/t/plotlyjs-jl-animation/70058/3) example, which does not work on my machine either for some reason (I use the newest versions of vscode, julia and plotly (as of march 2023)).  
Any help would be greatly appreciated! 🙂

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 20, 2023, 7:18am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/4 "2023-03-20T07:18:27Z")

</div>

Hi, here is the pretty much exact Julia translation from the JavaScript one I linked above. Can you try this out and see if it works with your setup?

> **Julia version**
>
> ```julia
> import CSV
> using DataFrames
> using PlotlyJS
> 
> k_fr = 6; # initial frame to display
> 
> rows = CSV.read("finance-charts-apple.csv", DataFrame);
> 
> x = rows[:,"Date"];
> yHi = rows[:,"AAPL.High"];
> yLo = rows[:,"AAPL.Low"];
> 
> n = 100;
> 
> frames = Vector{PlotlyFrame}(undef, n)
> for k in 1:n
> frames[k] = frame(data=[attr(x=x[1:k], #update x and y
> y=yLo[1:k],
> ),
> attr(x=x[1:k],
> y=yHi[1:k]
> )
> ],
> layout=attr(title_text="Test frame $k"),
> name="fr$k", #frame name 
> ) 
> end
> 
> trace1 = scatter(
> mode="lines",
> name="AAPL Low",
> x=frames[k_fr].data[1].x,
> y=frames[k_fr].data[1].y,
> line=attr(color="lightgrey")
> )
> 
> trace2 = scatter(
> mode="lines",
> name="AAPL High",
> fill="tonexty",
> x=frames[k_fr].data[2].x,
> y=frames[k_fr].data[2].y,
> line=attr(color="grey")
> )
> 
> data = [trace1, trace2]
> 
> layout = Layout(
> title="Multiple Trace Filled-Area Animation",
> xaxis=attr(
> range=[frames[n].data[1].x[1], frames[n].data[1].x[n]],
> showgrid=false
> ),
> yaxis=attr(
> range=[120, 140],
> showgrid=false
> ),
> legend=attr(
> orientation="h",
> x=0.5,
> y=1.2,
> xanchor="center"
> ),
> updatemenus=[
> attr(
> x=0.5,
> y=0,
> yanchor="top",
> xanchor="center",
> showactive=false,
> direction="left",
> type="buttons",
> pad=attr(t=87, r=10),
> buttons=[attr(
> label="Play",
> method="animate",
> args=[nothing, 
> attr(
> fromcurrent=true,
> transition=(
> duration=0,
> ),
> frame=attr(
> duration=40,
> redraw=false
> )
> )],
> ),
> attr(
> label="Pause",
> method="animate",
> args=[
> [nothing],
> attr(
> mode="immediate",
> transition=attr(
> duration=0
> ),
> frame=attr(
> duration=0,
> redraw=false
> )
> )
> ],
> )]
> )]
> );
> 
> pl = Plot(data, layout, frames)
> 
> ```

You’ll need to have added CSV.jl and DataFrames.jl for the data input step, and do this first in your working directory:

```julia
shell> curl -O https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv

```

or somehow download the [linked CSV file](https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv).

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 21, 2023, 11:14am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/5 "2023-03-21T11:14:47Z")

</div>

Here is an adaptation of your original code:

1. Load this button attribute definition first:

> **Button attribute code**
>
> ```julia
> using PlotlyJS
> 
> DT = 1000;
> 
> buttons_attr = [attr(
> label="Play",
> method="animate",
> args=[nothing, 
> attr(
> fromcurrent=true,
> transition=(
> duration=DT,
> ),
> frame=attr(
> duration=DT,
> redraw=true
> )
> )],
> ),
> attr(
> label="Pause",
> method="animate",
> args=[
> [nothing],
> attr(
> mode="immediate",
> fromcurrent=true,
> transition=attr(
> duration=DT
> ),
> frame=attr(
> duration=DT,
> redraw=true
> )
> )
> ],
> )]
> 
> ```

1. The main plotting logic:

```julia
using PlotlyJS

d = 30
n = 20

#random matrices for heatmaps
Matrices = [rand(d,d) for i = 1:n]
colorscale = [[0, "white"], [1, "cyan"]]

# create the frames for the animation
frames = PlotlyFrame[
            frame(
                data=[attr(
                        z=Matrices[k],
                        colorscale=colorscale,
                     )
                    ],
                 layout=attr(title_text="Heatmap $k"), #update title
                 name="frame_$k", #frame name; 
        ) for k in 1:n ]

#generate the Plot data 
maps = [heatmap(z=Matrices[1], colorscale=colorscale)]    
    
layout = Layout(
        width=400, 
        height=400, 
        margin_b=90,
    # add buttons to play the animation
    updatemenus=[
    attr(
      x=0.5,
      y=0,
      yanchor="top",
      xanchor="center",
      showactive=true,
      direction="left",
      type="buttons",
      pad=attr(t=87, r=10),
      buttons=buttons_attr
    )]
    ) #end layout

# display the plot data
Plot(maps, layout, frames)

```

---

<div class="post-metadata">

**Author:** ![phiG](https://avatars.discourse-cdn.com/v4/letter/p/96bed5/32.png) [@phiG](https://discourse.julialang.org/u/phiG)\
**Post date:** [March 22, 2023, 5:10pm UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/6 "2023-03-22T17:10:38Z")

</div>

First of all thank you **very** much for your help and the time it must have taken you to write this and I’m sorry for not answering sooner. I have tried every combination I could think of and the buttons still do not do anything. I am using Julia version 1.8.5, PlotlyJS version 1.8.5 as well (at least that is what it says when I type “PlotlyJS.VERSION” in the Julia console), vscode version 1.76.2, Windows 11 22H2 and for viewing the plots I can also use Chrome 111.0.5563.110, in which the plot opens when I run my code in the Julia Terminal instead of inside vscode. My code now looks like this (sorry if it looks messy):

```julia
using PlotlyJS

Matrices = [rand(2, 2) for i = 1:5]
colorscale = [[0, "white"], [1, "cyan"]]

maps = Plot(
    heatmap(z = Matrices[1], colorscale = colorscale),
    Layout(
        width = 400,
        height = 400,
        margin_b = 90,
        sliders = [
            attr(
                active = 0,
                pad_t = 20,
                steps = [
                    attr(
                        method = "restyle",
                        label = "Heatmap $k",
                        args = [attr(z = (Matrices[k],), colorscale = (colorscale,))],
                    ) for k = 1:length(Matrices)
                ],
            ),
        ],
        updatemenus = [
            attr(
                type = "buttons",
                buttons = [
                    attr(
                        label = "Play",
                        method = "animate",
                        args = [
                            nothing,
                            attr(
                                fromcurrent = true,
                                transition = (duration = 0,),
                                frame = attr(duration = 1000, redraw = true),
                            ),
                        ],
                    ),
                    attr(
                        label = "Pause",
                        method = "animate",
                        args = [
                            [nothing],
                            attr(
                                mode = "immediate",
                                fromcurrent = true,
                                transition = attr(duration = 0),
                                frame = attr(duration = 1000, redraw = true),
                            ),
                        ],
                    ),
                ],
            ),
        ],
    ),
)

display(maps)

```

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 22, 2023, 11:21pm UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/7 "2023-03-22T23:21:09Z")

</div>

It looks like you’re missing the frames component for your example; see my example above. You need `Plot(maps, layout, *frames*)`.

That said, there seems to be an issue in VSCode for me as well when trying to play animations; I can only get the play button to work when running through the terminal and opening in a browser.

---

<div class="post-metadata">

**Author:** ![phiG](https://avatars.discourse-cdn.com/v4/letter/p/96bed5/32.png) [@phiG](https://discourse.julialang.org/u/phiG)\
**Post date:** [March 23, 2023, 7:55am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/8 "2023-03-23T07:55:42Z")

</div>

Thank you so much! Now I finally get it, and you’re right the buttons only work in the browser (but at least they work there). I will share my improved version later as soon as I have the time for it.

---

<div class="post-metadata">

**Author:** ![phiG](https://avatars.discourse-cdn.com/v4/letter/p/96bed5/32.png) [@phiG](https://discourse.julialang.org/u/phiG)\
**Post date:** [March 23, 2023, 5:05pm UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/9 "2023-03-23T17:05:11Z")

</div>

As promised, here is now my updated code thanks to you! I also re-added the sliders in two different ways, as explained below. Also, the example [here](https://discourse.julialang.org/t/plotlyjs-jl-animation/70058/3) which I had mentioned above was not working, indeed does work but again not in vscode. At that time I did not yet found out that we have to paste the code into the Julia Terminal /view it in a browser.

My first code does not combine the sliders into the updatemenus attribute. That means when pressing the play button, the slider does not update its position respective to the played frame but works indepentently. The second code below combines everything.

FIRST CODE

```julia
#Code for generating a plotly plot with multiple frames.
#The individual frames can be viewed by clicking and dragging a slider or with clicking the play/pause buttons. 
#The buttons only work when viewing the plot in a browser (which will automatically open when pasting the code into the Julia Terminal).
using PlotlyJS

#data to be plotted: a vector of random matrices
Matrices = [rand(2, 2) for i = 1:100]

#define colorscheme for the plot
colorscale = [[0, "white"], [1, "cyan"]]

#generate the initial frame
maps = [heatmap(z = Matrices[1], colorscale = colorscale)]

#store all frames in a vector
frames = PlotlyFrame[
    frame(
        data = [attr(z = Matrices[k], colorscale = colorscale)],
        layout = attr(title_text = "Heatmap $k"), #update title
        name = "frame_$k", #update frame name
    ) for k = 1:length(Matrices)
]

#define the slider for manually viewing the frames
sliders_attr = [
    attr(
        active = 0,
        pad_t = 10,
        steps = [
            attr(
                method = "restyle",
                label = "Heatmap $k",
                args = [attr(z = (Matrices[k],), colorscale = (colorscale,))],
            ) for k = 1:length(Matrices)
        ],
    ),
]

#define the displaying time per played frame (in milliseconds)
dt_frame = 250

#define the play and pause buttons
buttons_attr = [
    attr(
        label = "Play",
        method = "animate",
        args = [
            nothing,
            attr(
                fromcurrent = true,
                transition = (duration = dt_frame,),
                frame = attr(duration = dt_frame, redraw = true),
            ),
        ],
    ),
    attr(
        label = "Pause",
        method = "animate",
        args = [
            [nothing],
            attr(
                mode = "immediate",
                fromcurrent = true,
                transition = attr(duration = dt_frame),
                frame = attr(duration = dt_frame, redraw = true),
            ),
        ],
    ),
]

#layout for the plot
layout = Layout(
    width = 500,
    height = 500,
    margin_b = 90,
    # add buttons to play the animation
    updatemenus = [
        attr(
            x = 0.5,
            y = 0,
            yanchor = "top",
            xanchor = "center",
            showactive = true,
            direction = "left",
            type = "buttons",
            pad = attr(t = 90, r = 10),
            buttons = buttons_attr,
        ),
    ],
    #add the sliders
    sliders = sliders_attr,
)

#save the plot and show it
plotdata = Plot(maps, layout, frames)
display(plotdata)

```

SECOND CODE

```julia
#Code for generating a plotly plot with multiple frames.
#The individual frames can be viewed by clicking and dragging a slider or with clicking the play/pause buttons. 
#The buttons only work when viewing the plot in a browser (which will automatically open when pasting the code into the Julia Terminal).
using PlotlyJS

#data to be plotted: a vector of random matrices
Matrices = [rand(2, 2) for i = 1:100]

#define colorscheme for the plot
colorscale = [[0, "white"], [1, "cyan"]]

#generate the initial frame
trace = [heatmap(z = Matrices[1], colorscale = colorscale)]

#store all frames in a vector
frames = PlotlyFrame[
    frame(
        data = [attr(z = Matrices[k], colorscale = colorscale)],
        layout = attr(title_text = "Heatmap $k"), #update title
        name = "frame_$k", #update frame name
        traces = [0],
    ) for k = 1:length(Matrices)
]

#define the slider for manually viewing the frames
sliders_attr = [
    attr(
        active = 0,
        minorticklen = 0,
        pad_t = 10,
        steps = [
            attr(
                method = "animate",
                label = "Heatmap $k",
                args = [
                    ["frame_$k"], #match the name of the frame again
                    attr(
                        mode = "immediate",
                        transition = attr(duration = 0),
                        frame = attr(duration = 5, redraw = true),
                    ),
                ],
            ) for k = 1:length(Matrices)
        ],
    ),
]

#define the displaying time per played frame (in milliseconds)
dt_frame = 250

#define the play and pause buttons
buttons_attr = [
    attr(
        label = "Play",
        method = "animate",
        args = [
            nothing,
            attr(
                fromcurrent = true,
                transition = (duration = dt_frame,),
                frame = attr(duration = dt_frame, redraw = true),
            ),
        ],
    ),
    attr(
        label = "Pause",
        method = "animate",
        args = [
            [nothing],
            attr(
                mode = "immediate",
                fromcurrent = true,
                transition = attr(duration = dt_frame),
                frame = attr(duration = dt_frame, redraw = true),
            ),
        ],
    ),
]

#layout for the plot
layout = Layout(
    width = 500,
    height = 500,
    margin_b = 90,
    # add buttons to play the animation
    updatemenus = [
        attr(
            x = 0.5,
            y = 0,
            yanchor = "top",
            xanchor = "center",
            showactive = true,
            direction = "left",
            type = "buttons",
            pad = attr(t = 90, r = 10),
            buttons = buttons_attr,
        ),
    ],
    #add the sliders
    sliders = sliders_attr,
)

#save the plot and show it
plotdata = Plot(trace, layout, frames)
display(plotdata)

```

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 24, 2023, 1:44am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/10 "2023-03-24T01:44:12Z")

</div>

Well done on the second example, I couldn’t figure out how to combine _both_ sliders and frames, and you’ve provided a nice demonstration.

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [March 24, 2023, 2:05am UTC](https://discourse.julialang.org/t/adding-a-play-button-to-a-plotlyjs-plot/95383/11 "2023-03-24T02:05:22Z")

</div>

The only additional suggestion I would make is to specify your `colorscale` bounds to stop the erratic changes between frames, by using [zmax](https://plotly.com/julia/reference/#heatmap-zmax) and [zmin](https://plotly.com/julia/reference/#heatmap-zmin).

That is, change the line

```julia
data = [attr(z = Matrices[k], colorscale = colorscale)],

```

to

```julia
data = [attr(z = Matrices[k], colorscale = colorscale, zmin=0, zmax=1)],

```
