Skip to content

Commit 82a62ff

Browse files
TakodaSjonmmease
authored andcommitted
Adding auto start animation_opts argument to html export and html renderers (#1503)
1 parent bb5c998 commit 82a62ff

File tree

4 files changed

+124
-20
lines changed

4 files changed

+124
-20
lines changed

plotly/io/_base_renderers.py

+34-11
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ def __init__(self,
229229
global_init=False,
230230
config=None,
231231
auto_play=False,
232-
post_script=None):
232+
post_script=None,
233+
animation_opts=None):
233234

234235
self.config = dict(config) if config else {}
235236
self.auto_play = auto_play
@@ -238,6 +239,7 @@ def __init__(self,
238239
self.requirejs = requirejs
239240
self.full_html = full_html
240241
self.post_script = post_script
242+
self.animation_opts = animation_opts
241243

242244
def activate(self):
243245
if self.global_init:
@@ -315,7 +317,8 @@ def to_mimebundle(self, fig_dict):
315317
include_plotlyjs=include_plotlyjs,
316318
include_mathjax=include_mathjax,
317319
post_script=self.post_script,
318-
full_html=self.full_html)
320+
full_html=self.full_html,
321+
animation_opts=self.animation_opts)
319322

320323
return {'text/html': html}
321324

@@ -336,15 +339,17 @@ def __init__(self,
336339
connected=False,
337340
config=None,
338341
auto_play=False,
339-
post_script=None):
342+
post_script=None,
343+
animation_opts=None):
340344
super(NotebookRenderer, self).__init__(
341345
connected=connected,
342346
full_html=False,
343347
requirejs=True,
344348
global_init=True,
345349
config=config,
346350
auto_play=auto_play,
347-
post_script=post_script)
351+
post_script=post_script,
352+
animation_opts=animation_opts)
348353

349354

350355
class KaggleRenderer(HtmlRenderer):
@@ -358,15 +363,21 @@ class KaggleRenderer(HtmlRenderer):
358363
359364
mime type: 'text/html'
360365
"""
361-
def __init__(self, config=None, auto_play=False, post_script=None):
366+
def __init__(self,
367+
config=None,
368+
auto_play=False,
369+
post_script=None,
370+
animation_opts=None):
371+
362372
super(KaggleRenderer, self).__init__(
363373
connected=True,
364374
full_html=False,
365375
requirejs=True,
366376
global_init=True,
367377
config=config,
368378
auto_play=auto_play,
369-
post_script=post_script)
379+
post_script=post_script,
380+
animation_opts=animation_opts)
370381

371382

372383
class ColabRenderer(HtmlRenderer):
@@ -377,15 +388,21 @@ class ColabRenderer(HtmlRenderer):
377388
378389
mime type: 'text/html'
379390
"""
380-
def __init__(self, config=None, auto_play=False, post_script=None):
391+
def __init__(self,
392+
config=None,
393+
auto_play=False,
394+
post_script=None,
395+
animation_opts=None):
396+
381397
super(ColabRenderer, self).__init__(
382398
connected=True,
383399
full_html=True,
384400
requirejs=False,
385401
global_init=False,
386402
config=config,
387403
auto_play=auto_play,
388-
post_script=post_script)
404+
post_script=post_script,
405+
animation_opts=animation_opts)
389406

390407

391408
class IFrameRenderer(MimetypeRenderer):
@@ -414,11 +431,13 @@ class IFrameRenderer(MimetypeRenderer):
414431
def __init__(self,
415432
config=None,
416433
auto_play=False,
417-
post_script=None):
434+
post_script=None,
435+
animation_opts=None):
418436

419437
self.config = config
420438
self.auto_play = auto_play
421439
self.post_script = post_script
440+
self.animation_opts = animation_opts
422441

423442
def to_mimebundle(self, fig_dict):
424443
from plotly.io import write_html
@@ -457,6 +476,7 @@ def to_mimebundle(self, fig_dict):
457476
include_mathjax='cdn',
458477
auto_open=False,
459478
post_script=self.post_script,
479+
animation_opts=self.animation_opts,
460480
validate=False)
461481

462482
# Build IFrame
@@ -547,14 +567,16 @@ def __init__(self,
547567
using=None,
548568
new=0,
549569
autoraise=True,
550-
post_script=None):
570+
post_script=None,
571+
animation_opts=None):
551572

552573
self.config = config
553574
self.auto_play = auto_play
554575
self.using = using
555576
self.new = new
556577
self.autoraise = autoraise
557578
self.post_script = post_script
579+
self.animation_opts = animation_opts
558580

559581
def render(self, fig_dict):
560582
renderer = HtmlRenderer(
@@ -564,7 +586,8 @@ def render(self, fig_dict):
564586
global_init=False,
565587
config=self.config,
566588
auto_play=self.auto_play,
567-
post_script=self.post_script)
589+
post_script=self.post_script,
590+
animation_opts=self.animation_opts)
568591

569592
bundle = renderer.to_mimebundle(fig_dict)
570593
html = bundle['text/html']

plotly/io/_html.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def to_html(fig,
3030
include_mathjax=False,
3131
post_script=None,
3232
full_html=True,
33+
animation_opts=None,
3334
validate=True):
3435
"""
3536
Convert a figure to an HTML string representation.
@@ -102,6 +103,12 @@ def to_html(fig,
102103
If True, produce a string containing a complete HTML document
103104
starting with an <html> tag. If False, produce a string containing
104105
a single <div> element.
106+
animation_opts: dict or None (default None)
107+
dict of custom animation parameters to be passed to the function
108+
Plotly.animate in Plotly.js. See
109+
https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
110+
for available options. Has no effect if the figure does not contain
111+
frames, or auto_play is False.
105112
validate: bool (default True)
106113
True if the figure should be validated before being converted to
107114
JSON, False otherwise.
@@ -164,9 +171,14 @@ def to_html(fig,
164171
}})""".format(id=plotdivid, frames=jframes)
165172

166173
if auto_play:
174+
if animation_opts:
175+
animation_opts_arg = ', ' + json.dumps(animation_opts)
176+
else:
177+
animation_opts_arg = ''
167178
then_animate = """.then(function(){{
168-
Plotly.animate('{id}');
169-
}})""".format(id=plotdivid)
179+
Plotly.animate('{id}', null{animation_opts});
180+
}})""".format(id=plotdivid,
181+
animation_opts=animation_opts_arg)
170182

171183
script = """
172184
if (document.getElementById("{id}")) {{
@@ -299,6 +311,7 @@ def write_html(fig,
299311
include_mathjax=False,
300312
post_script=None,
301313
full_html=True,
314+
animation_opts=None,
302315
validate=True,
303316
auto_open=False):
304317
"""
@@ -390,6 +403,12 @@ def write_html(fig,
390403
If True, produce a string containing a complete HTML document
391404
starting with an <html> tag. If False, produce a string containing
392405
a single <div> element.
406+
animation_opts: dict or None (default None)
407+
dict of custom animation parameters to be passed to the function
408+
Plotly.animate in Plotly.js. See
409+
https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
410+
for available options. Has no effect if the figure does not contain
411+
frames, or auto_play is False.
393412
validate: bool (default True)
394413
True if the figure should be validated before being converted to
395414
JSON, False otherwise.
@@ -411,7 +430,8 @@ def write_html(fig,
411430
include_mathjax=include_mathjax,
412431
post_script=post_script,
413432
full_html=full_html,
414-
validate=validate)
433+
validate=validate,
434+
animation_opts=animation_opts)
415435

416436
# Check if file is a string
417437
file_is_str = isinstance(file, six.string_types)

plotly/offline/offline.py

+46-4
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ def init_notebook_mode(connected=False):
294294

295295
def iplot(figure_or_data, show_link=False, link_text='Export to plot.ly',
296296
validate=True, image=None, filename='plot_image', image_width=800,
297-
image_height=600, config=None, auto_play=True):
297+
image_height=600, config=None, auto_play=True, animation_opts=None):
298298
"""
299299
Draw plotly graphs inside an IPython or Jupyter notebook
300300
@@ -329,6 +329,11 @@ def iplot(figure_or_data, show_link=False, link_text='Export to plot.ly',
329329
auto_play (default=True) -- Whether to automatically start the animation
330330
sequence if the figure contains frames. Has no effect if the figure
331331
does not contain frames.
332+
animation_opts (default=None) -- dict of custom animation parameters to be
333+
passed to the function Plotly.animate in Plotly.js. See
334+
https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
335+
for available options. Has no effect if the figure
336+
does not contain frames, or auto_play is False.
332337
333338
Example:
334339
```
@@ -339,6 +344,20 @@ def iplot(figure_or_data, show_link=False, link_text='Export to plot.ly',
339344
format you want. e.g. `image='png'`
340345
iplot([{'x': [1, 2, 3], 'y': [5, 2, 7]}], image='png')
341346
```
347+
348+
animation_opts Example:
349+
```
350+
from plotly.offline import iplot
351+
figure = {'data': [{'x': [0, 1], 'y': [0, 1]}],
352+
'layout': {'xaxis': {'range': [0, 5], 'autorange': False},
353+
'yaxis': {'range': [0, 5], 'autorange': False},
354+
'title': 'Start Title'},
355+
'frames': [{'data': [{'x': [1, 2], 'y': [1, 2]}]},
356+
{'data': [{'x': [1, 4], 'y': [1, 4]}]},
357+
{'data': [{'x': [3, 4], 'y': [3, 4]}],
358+
'layout': {'title': 'End Title'}}]}
359+
iplot(figure,animation_opts="{frame: {duration: 1}}")
360+
```
342361
"""
343362
import plotly.io as pio
344363

@@ -361,14 +380,16 @@ def iplot(figure_or_data, show_link=False, link_text='Export to plot.ly',
361380
validate=validate,
362381
config=config,
363382
auto_play=auto_play,
364-
post_script=post_script)
383+
post_script=post_script,
384+
animation_opts=animation_opts)
365385

366386

367387
def plot(figure_or_data, show_link=False, link_text='Export to plot.ly',
368388
validate=True, output_type='file', include_plotlyjs=True,
369389
filename='temp-plot.html', auto_open=True, image=None,
370390
image_filename='plot_image', image_width=800, image_height=600,
371-
config=None, include_mathjax=False, auto_play=True):
391+
config=None, include_mathjax=False, auto_play=True,
392+
animation_opts=None):
372393
""" Create a plotly graph locally as an HTML document or string.
373394
374395
Example:
@@ -481,6 +502,25 @@ def plot(figure_or_data, show_link=False, link_text='Export to plot.ly',
481502
auto_play (default=True) -- Whether to automatically start the animation
482503
sequence on page load if the figure contains frames. Has no effect if
483504
the figure does not contain frames.
505+
animation_opts (default=None) -- dict of custom animation parameters to be
506+
passed to the function Plotly.animate in Plotly.js. See
507+
https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
508+
for available options. Has no effect if the figure does not contain
509+
frames, or auto_play is False.
510+
511+
Example:
512+
```
513+
from plotly.offline import plot
514+
figure = {'data': [{'x': [0, 1], 'y': [0, 1]}],
515+
'layout': {'xaxis': {'range': [0, 5], 'autorange': False},
516+
'yaxis': {'range': [0, 5], 'autorange': False},
517+
'title': 'Start Title'},
518+
'frames': [{'data': [{'x': [1, 2], 'y': [1, 2]}]},
519+
{'data': [{'x': [1, 4], 'y': [1, 4]}]},
520+
{'data': [{'x': [3, 4], 'y': [3, 4]}],
521+
'layout': {'title': 'End Title'}}]}
522+
plot(figure,animation_opts="{frame: {duration: 1}}")
523+
```
484524
"""
485525
import plotly.io as pio
486526

@@ -522,6 +562,7 @@ def plot(figure_or_data, show_link=False, link_text='Export to plot.ly',
522562
post_script=post_script,
523563
full_html=True,
524564
validate=validate,
565+
animation_opts=animation_opts,
525566
auto_open=auto_open)
526567
return filename
527568
else:
@@ -533,7 +574,8 @@ def plot(figure_or_data, show_link=False, link_text='Export to plot.ly',
533574
include_mathjax=include_mathjax,
534575
post_script=post_script,
535576
full_html=False,
536-
validate=validate)
577+
validate=validate,
578+
animation_opts=animation_opts)
537579

538580

539581
def plot_mpl(mpl_fig, resize=False, strip_style=False,

plotly/tests/test_core/test_offline/test_offline.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -418,9 +418,28 @@ def test_auto_play(self):
418418

419419
def test_no_auto_play(self):
420420
html = plotly.offline.plot(
421-
fig_frames, output_type='div',auto_play=False)
421+
fig_frames, output_type='div', auto_play=False)
422+
self.assertIn(add_frames, html)
423+
self.assertNotIn(do_auto_play, html)
424+
425+
def test_animation_opts(self):
426+
animation_opts = {'frame': {'duration': 5000}}
427+
expected_opts_str = json.dumps(animation_opts)
428+
429+
# When auto_play is False, animation options are skipped
430+
html = plotly.offline.plot(
431+
fig_frames, output_type='div', auto_play=False, animation_opts=animation_opts)
422432
self.assertIn(add_frames, html)
423433
self.assertNotIn(do_auto_play, html)
434+
self.assertNotIn(expected_opts_str, html)
435+
436+
# When auto_play is True, animation options are included
437+
html = plotly.offline.plot(
438+
fig_frames, output_type='div', auto_play=True,
439+
animation_opts=animation_opts)
440+
self.assertIn(add_frames, html)
441+
self.assertIn(do_auto_play, html)
442+
self.assertIn(expected_opts_str, html)
424443

425444
def test_download_image(self):
426445
# Not download image by default
@@ -431,4 +450,4 @@ def test_download_image(self):
431450
# Request download image
432451
html = plotly.offline.plot(
433452
fig_frames, output_type='div', auto_play=False, image='png')
434-
self.assertIn(download_image, html)
453+
self.assertIn(download_image, html)

0 commit comments

Comments
 (0)