Skip to content

Commit b75deec

Browse files
authored
Merge pull request #399 from plotly/animations
Animations - Only in Offline mode
2 parents 6739f29 + 8e45ad8 commit b75deec

File tree

5 files changed

+735
-36
lines changed

5 files changed

+735
-36
lines changed

plotly/plotly_offline_aux/plotlyoffline.m

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66
% create dependency string unless not required
77
if plotlyfig.PlotOptions.IncludePlotlyjs
88
% grab the bundled dependencies
9-
userhome = getuserdir();
10-
plotly_config_folder = fullfile(userhome,'.plotly');
11-
plotly_js_folder = fullfile(plotly_config_folder, 'plotlyjs');
12-
bundle_name = 'plotly-matlab-offline-bundle.js';
13-
bundle_file = fullfile(plotly_js_folder, bundle_name);
9+
userHome = getuserdir();
10+
plotlyConfigFolder = fullfile(userHome,'.plotly');
11+
plotlyJSFolder = fullfile(plotlyConfigFolder, 'plotlyjs');
12+
bundleName = 'plotly-matlab-offline-bundle.js';
13+
bundleFile = fullfile(plotlyJSFolder, bundleName);
1414

1515
% check that the bundle exists
1616
try
17-
bundle = fileread(bundle_file);
17+
bundle = fileread(bundleFile);
1818
% template dependencies
19-
dep_script = sprintf('<script type="text/javascript">%s</script>\n', ...
19+
depScript = sprintf('<script type="text/javascript">%s</script>\n', ...
2020
bundle);
2121
catch
2222
error(['Error reading: %s.\nPlease download the required ', ...
2323
'dependencies using: >>getplotlyoffline \n', ...
2424
'or contact support@plot.ly for assistance.'], ...
25-
bundle_file);
25+
bundleFile);
2626
end
2727
else
28-
dep_script = '';
28+
depScript = '';
2929
end
3030

3131
% handle plot div specs
@@ -34,57 +34,59 @@
3434
height = [num2str(plotlyfig.layout.height) 'px'];
3535

3636
if plotlyfig.PlotOptions.ShowLinkText
37-
link_text = plotlyfig.PlotOptions.LinkText;
37+
linkText = plotlyfig.PlotOptions.LinkText;
3838
else
39-
link_text = '';
39+
linkText = '';
4040
end
4141

4242
% format the data and layout
43-
jdata = m2json(plotlyfig.data);
44-
jlayout = m2json(plotlyfig.layout);
45-
clean_jdata = escapechars(jdata);
46-
clean_jlayout = escapechars(jlayout);
43+
jData = m2json(plotlyfig.data);
44+
jLayout = m2json(plotlyfig.layout);
45+
jFrames = m2json(plotlyfig.frames);
46+
clean_jData = escapechars(jData);
47+
clean_jLayout = escapechars(jLayout);
48+
clean_jFrames = escapechars(jFrames);
4749

4850
% template environment vars
49-
plotly_domain = plotlyfig.UserData.PlotlyDomain;
50-
env_script = sprintf(['<script type="text/javascript">', ...
51+
plotlyDomain = plotlyfig.UserData.PlotlyDomain;
52+
envScript = sprintf(['<script type="text/javascript">', ...
5153
'window.PLOTLYENV=window.PLOTLYENV || {};', ...
5254
'window.PLOTLYENV.BASE_URL="%s";', ...
5355
'Plotly.LINKTEXT="%s";', ...
54-
'</script>'], plotly_domain, link_text);
55-
56+
'</script>'], plotlyDomain, linkText);
57+
5658
% template Plotly.plot
57-
script = sprintf(['\n Plotly.plot("%s", %s, %s).then(function(){'...
59+
script = sprintf(['\n Plotly.plot("%s", {\n"data": %s,\n"layout": %s,\n"frames": %s\n}).then(function(){'...
5860
'\n $(".%s.loading").remove();' ...
5961
'\n $(".link--embedview").text("%s");'...
60-
'\n });'], id, clean_jdata, clean_jlayout, ...
61-
id, link_text);
62-
63-
plotly_script = sprintf(['\n<div id="%s" style="height: %s;',...
62+
'\n });'], id, clean_jData, clean_jLayout, clean_jFrames,...
63+
id, linkText);
64+
65+
plotlyScript = sprintf(['\n<div id="%s" style="height: %s;',...
6466
'width: %s;" class="plotly-graph-div">' ...
6567
'</div> \n<script type="text/javascript">' ...
6668
'%s \n</script>'], id, height, width, ...
6769
script);
6870

6971
% template entire script
70-
offline_script = [dep_script env_script plotly_script];
72+
offlineScript = [depScript envScript plotlyScript];
7173
filename = plotlyfig.PlotOptions.FileName;
7274
if iscellstr(filename), filename = sprintf('%s ', filename{:}); end
7375

7476
% remove the whitespace from the filename
75-
clean_filename = filename(filename~=' ');
76-
html_filename = [clean_filename '.html'];
77+
cleanFilename = filename(filename~=' ');
78+
htmlFilename = [cleanFilename '.html'];
7779

7880
% save the html file in the working directory
79-
plotly_offline_file = fullfile(plotlyfig.PlotOptions.SaveFolder, html_filename);
80-
file_id = fopen(plotly_offline_file, 'w');
81-
fprintf(file_id, offline_script);
82-
fclose(file_id);
81+
plotlyOfflineFile = fullfile(plotlyfig.PlotOptions.SaveFolder, htmlFilename);
82+
fileID = fopen(plotlyOfflineFile, 'w');
83+
fprintf(fileID, offlineScript);
84+
fclose(fileID);
8385

84-
% remove any whitespace from the plotly_offline_file path
85-
plotly_offline_file = strrep(plotly_offline_file, ' ', '%20');
86+
% remove any whitespace from the plotlyOfflineFile path
87+
plotlyOfflineFile = strrep(plotlyOfflineFile, ' ', '%20');
8688

8789
% return the local file url to be rendered in the browser
88-
response = ['file:///' plotly_offline_file];
90+
response = ['file:///' plotlyOfflineFile];
8991

9092
end

plotly/plotlyfig.m

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
properties
55
data; % data of the plot
66
layout; % layout of the plot
7+
frames; % for animations
78
url; % url response of making post request
89
error; % error response of making post request
910
warning; % warning response of making post request
@@ -35,6 +36,7 @@
3536
%-Core-%
3637
obj.data = {};
3738
obj.layout = struct();
39+
obj.frames = {};
3840
obj.url = '';
3941

4042
obj.UserData.Verbose = true;
@@ -60,6 +62,8 @@
6062
obj.PlotOptions.is_headmap_axis = false;
6163
obj.PlotOptions.Quality = -1;
6264
obj.PlotOptions.Zmin = [];
65+
obj.PlotOptions.FrameDuration = 1; % in ms.
66+
obj.PlotOptions.FrameTransitionDuration = 0; % in ms.
6367
obj.PlotOptions.geoRenderType = 'geo';
6468

6569
% offline options
@@ -252,6 +256,16 @@
252256
if(strcmpi(varargin{a},'Zmin'))
253257
obj.PlotOptions.Zmin = varargin{a+1};
254258
end
259+
if(strcmpi(varargin{a},'FrameDuration'))
260+
if varargin{a+1} > 0
261+
obj.PlotOptions.FrameDuration = varargin{a+1};
262+
end
263+
end
264+
if(strcmpi(varargin{a},'FrameTransitionDuration'))
265+
if varargin{a+1} >= 0
266+
obj.PlotOptions.FrameTransitionDuration = varargin{a+1};
267+
end
268+
end
255269
if(strcmpi(varargin{a},'geoRenderType'))
256270
obj.PlotOptions.geoRenderType = varargin{a+1};
257271
end
@@ -541,7 +555,7 @@ function validate(obj)
541555
web(response.url, '-browser');
542556
end
543557
else
544-
obj.url = plotlyoffline(obj);
558+
obj.url = plotlyoffline(obj);
545559
if obj.PlotOptions.OpenURL
546560
web(obj.url, '-browser');
547561
end

plotly/plotlyfig_aux/core/updateData.m

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
elseif strcmpi(obj.PlotOptions.TreatAs, 'bar3h')
2929
updateBar3h(obj, dataIndex);
3030
elseif strcmpi(obj.PlotOptions.TreatAs, 'surf')
31-
updateSurf(obj, dataIndex);
31+
updateSurf(obj, dataIndex);
32+
elseif strcmpi(obj.PlotOptions.TreatAs, 'comet') || strcmpi(obj.PlotOptions.TreatAs, 'comet3')
33+
updateComet(obj, dataIndex);
3234
elseif strcmpi(obj.PlotOptions.TreatAs, 'fmesh')
3335
updateFmesh(obj, dataIndex);
3436
elseif strcmpi(obj.PlotOptions.TreatAs, 'mesh')
@@ -103,6 +105,8 @@
103105
updateArea(obj, dataIndex);
104106
case 'areaseries'
105107
updateAreaseries(obj, dataIndex);
108+
case 'animatedline'
109+
updateAnimatedLine(obj, dataIndex);
106110
case 'bar'
107111
updateBar(obj, dataIndex);
108112
case 'barseries'
@@ -211,4 +215,42 @@
211215

212216
%-------------------------------------------------------------------------%
213217

218+
try
219+
if obj.layout.isAnimation
220+
%- Play Button Options-%
221+
opts{1} = nan;
222+
opts{2}.frame.duration = obj.PlotOptions.FrameDuration;
223+
opts{2}.frame.redraw = true;
224+
opts{2}.fromcurrent = true;
225+
opts{2}.mode = 'immediate';
226+
opts{2}.transition.duration = obj.PlotOptions.FrameTransitionDuration;
227+
228+
button{1}.label = '&#9654;';
229+
button{1}.method = 'animate';
230+
button{1}.args = opts;
231+
232+
opts{1} = {nan};
233+
opts{2}.transition.duration = 0;
234+
opts{2}.frame.duration = 0;
235+
236+
button{2}.label = '&#9724;';
237+
button{2}.method = 'animate';
238+
button{2}.args = opts;
239+
240+
obj.layout.updatemenus{1}.type = 'buttons';
241+
obj.layout.updatemenus{1}.buttons = button;
242+
obj.layout.updatemenus{1}.pad.r = 70;
243+
obj.layout.updatemenus{1}.pad.t = 10;
244+
obj.layout.updatemenus{1}.direction = 'left';
245+
obj.layout.updatemenus{1}.showactive = true;
246+
obj.layout.updatemenus{1}.x = 0.01;
247+
obj.layout.updatemenus{1}.y = 0.01;
248+
obj.layout.updatemenus{1}.xanchor = 'left';
249+
obj.layout.updatemenus{1}.yanchor = 'top';
250+
251+
obj.layout = rmfield(obj.layout,'isAnimation');
252+
end
253+
catch
254+
end
255+
214256
end

0 commit comments

Comments
 (0)