Skip to content

Commit 17b5ab1

Browse files
committed
Render static image versions of figures on notebook load
and replace them with full interactive version on hover.
1 parent 8bce92d commit 17b5ab1

File tree

1 file changed

+77
-2
lines changed

1 file changed

+77
-2
lines changed

packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,90 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer {
4141
super();
4242
this.addClass(CSS_CLASS);
4343
this._mimeType = options.mimeType;
44+
45+
this._img_el = <HTMLImageElement>(document.createElement("img"));
46+
this._img_el.className = 'plot-img';
47+
this.node.appendChild(this._img_el);
48+
49+
// Install hover callback
50+
this._img_el.addEventListener('mouseenter', event => {
51+
this.createGraph(this._model);
52+
})
4453
}
4554

4655
/**
4756
* Render Plotly into this widget's node.
4857
*/
4958
renderModel(model: IRenderMime.IMimeModel): Promise<void> {
59+
60+
if (this.hasGraphElement()) {
61+
// We already have a graph, don't overwrite it
62+
return Promise.resolve();
63+
}
64+
65+
this._model = model;
66+
67+
const png_data = <string>model.data['image/png'];
68+
if(png_data !== undefined && png_data !== null) {
69+
// We have PNG data, use it
70+
this.createImage(png_data);
71+
return Promise.resolve();
72+
} else {
73+
// Create a new graph
74+
return this.createGraph(model);
75+
}
76+
}
77+
78+
private hasGraphElement() {
79+
return this.node.querySelector('.plot-container') !== null
80+
}
81+
82+
private createImage(png_data: string) {
83+
this.hideGraph();
84+
this._img_el.src = "data:image/png;base64," + <string>png_data;
85+
this.showImage();
86+
}
87+
88+
private hideGraph() {
89+
// Hide any graph
90+
let el = <HTMLDivElement>this.node.querySelector('.plot-container');
91+
if (el !== null && el !== undefined) {
92+
el.style.display = "none"
93+
}
94+
}
95+
96+
private showGraph() {
97+
// Hide any graph
98+
let el = <HTMLDivElement>this.node.querySelector('.plot-container');
99+
if (el !== null && el !== undefined) {
100+
el.style.display = "block"
101+
}
102+
}
103+
104+
private hideImage() {
105+
// Hide any graph
106+
let el = <HTMLImageElement>this.node.querySelector('.plot-img');
107+
if (el !== null && el !== undefined) {
108+
el.style.display = "none"
109+
}
110+
}
111+
112+
private showImage() {
113+
// Hide any graph
114+
let el = <HTMLImageElement>this.node.querySelector('.plot-img');
115+
if (el !== null && el !== undefined) {
116+
el.style.display = "block"
117+
}
118+
}
119+
120+
private createGraph(model: IRenderMime.IMimeModel) {
50121
const { data, layout, frames, config } = model.data[this._mimeType] as
51122
| any
52123
| IPlotlySpec;
53-
// const metadata = model.metadata[this._mimeType] as any || {};
124+
54125
return Plotly.react(this.node, data, layout, config).then(plot => {
126+
this.showGraph();
127+
this.hideImage();
55128
this.update();
56129
if (frames) {
57130
Plotly.addFrames(this.node, frames).then(() => {
@@ -96,14 +169,16 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer {
96169
* A message handler invoked on an `'update-request'` message.
97170
*/
98171
protected onUpdateRequest(msg: Message): void {
99-
if (this.isVisible) {
172+
if (this.isVisible && this.hasGraphElement()) {
100173
Plotly.redraw(this.node).then(() => {
101174
Plotly.Plots.resize(this.node);
102175
});
103176
}
104177
}
105178

106179
private _mimeType: string;
180+
private _img_el: HTMLImageElement;
181+
private _model: IRenderMime.IMimeModel
107182
}
108183

109184
/**

0 commit comments

Comments
 (0)