Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Description
Problem
Let's take the example fromhttps://matplotlib.org/stable/gallery/animation/animate_decay.html
importitertoolsimportnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib.animationasanimationdefdata_gen():forcntinitertools.count():t=cnt/10yieldt,np.sin(2*np.pi*t)*np.exp(-t/10.)definit():ax.set_ylim(-1.1,1.1)ax.set_xlim(0,10)delxdata[:]delydata[:]line.set_data(xdata,ydata)returnline,fig,ax=plt.subplots()line,=ax.plot([], [],lw=2)ax.grid()xdata,ydata= [], []defrun(data):# update the datat,y=dataxdata.append(t)ydata.append(y)xmin,xmax=ax.get_xlim()ift>=xmax:ax.set_xlim(xmin,2*xmax)ax.figure.canvas.draw()line.set_data(xdata,ydata)returnline,ani=animation.FuncAnimation(fig,run,data_gen,interval=10,init_func=init)plt.show()
It works great and I can easily save the animation to html using code such as:
frommatplotlib.animationimportHTMLWriterfname="path/to/myfile.html"writer=HTMLWriter(fps=5)writer.frame_format="svg"# Ensure svg formatani.save(fname,writer=writer)
I can open the html animation from a browser or display it in a jupyter notebook:
fromIPython.displayimportHTML# Display the animationHTML(fname_html.read_text())
The problem is that within the html file, the path to the frames is hardcoded rather than being relative to the
html file. So if you change the location of the html file, it does not work anymore.
<scriptlanguage="javascript"> /* Instantiate the Animation class. */ /* The IDs given should match those used in the template above. */ (function(){varimg_id="_anim_imga5cbaf4d0c4c4ffda374436a276eff4b";varslider_id="_anim_slidera5cbaf4d0c4c4ffda374436a276eff4b";varloop_select_id="_anim_loop_selecta5cbaf4d0c4c4ffda374436a276eff4b";varframes=newArray(100);for(vari=0;i<100;i++){frames[i]="path/to/myfile_frames/frame"+("0000000"+i).slice(-7)+".svg";} /* set a timeout to make sure all the above elements are created before the object is initialized. */ setTimeout(function(){anima5cbaf4d0c4c4ffda374436a276eff4b=newAnimation(frames,img_id,slider_id,200,loop_select_id);}, 0);})()</script>
You can feedani.save(fname, writer=writer)
with a relativefname
but in that case, it works in jupyter only if the html file is in the same folder than the notebook.
Proposed solution
The best would be to modify the javascript so it can get the path of the html file on the fly. I tried:
<scriptlanguage="javascript"> /* Instantiate the Animation class. */ /* The IDs given should match those used in the template above. */ (function(){varimg_id="_anim_imga5cbaf4d0c4c4ffda374436a276eff4b";varslider_id="_anim_slidera5cbaf4d0c4c4ffda374436a276eff4b";varloop_select_id="_anim_loop_selecta5cbaf4d0c4c4ffda374436a276eff4b";varframes=newArray(100);varscripts=document.getElementsByTagName("script"),src=scripts[scripts.length-1].src;for(vari=0;i<100;i++){frames[i]=src+"myfile_frames/frame"+("0000000"+i).slice(-7)+".svg";} /* set a timeout to make sure all the above elements are created before the object is initialized. */ setTimeout(function(){anima5cbaf4d0c4c4ffda374436a276eff4b=newAnimation(frames,img_id,slider_id,200,loop_select_id);}, 0);})()</script>
And it works at least in Firefox and Chrome. However, it does not work for:
fromIPython.displayimportHTML# Display the animationHTML(fname_html.read_text())