Work with Plotly

If you want interactive plots on some pages and are not afraid of using heavy javascript libraries, then Plotly is a nice library. The Julia wrapper PlotlyJS.jl can be used to generate Plotly plots.

Pre-requisites

Download plotly.min.js saving it to /_libs/plotly/plotly.min.js.

Then create a variable hasplotly with default value false: in your config.md write

@def hasplotly = false

Finally, in your src/_layout/head.html add

{{if hasplotly}}
  <script src="/libs/plotly/plotly.min.js"></script> 
  <script>
    // This function is used when calling `\fig{...}` See # Using \fig{...} below
    const PlotlyJS_json = async (div, url) => {
      response = await fetch(url); // get file
      fig = await response.json(); // convert it to json
      // Make the plot fit the screen responsively. See the documentation of plotly.js. https://plotly.com/javascript/responsive-fluid-layout/
      if (typeof fig.config === 'undefined') { fig["config"]={} }
      delete fig.layout.width
      delete fig.layout.height
      fig["layout"]["autosize"] = true
      fig["config"]["autosizable"] = true
      fig["config"]["responsive"] = true

      // make it easier to scroll throught the website rather than being blocked by a figure.
      fig.config["scrollZoom"] = false

      // PlotlyJS.savefig by default add the some more attribute to make a static plot.
      // Disable them to make the website fancier.
      delete fig.config.staticPlot
      delete fig.config.displayModeBar
      delete fig.config.doubleClick
      delete fig.config.showTips

      Plotly.newPlot(div, fig);
    };
  </script>
  {{end}}

Offline-generated plot

Assuming you already have the Plotly code for some plot, displaying the result on a page with Franklin is now pretty straightforward. Start by adding

@def hasplotly = true

so that the JS library will be loaded then somewhere appropriate add:

~~~
<div id="tester" style="width:600px;height:350px;"></div>

<script>
	TESTER = document.getElementById('tester');
	Plotly.newPlot( TESTER, [{
	x: [1, 2, 3, 4, 5],
	y: [1, 2, 4, 8, 16] }], {
	margin: { t: 0 } } );
</script>
~~~

This will give:

Live-generated plot

One step further is to use PlotlyJS to define a plot and then pass the result to Franklin. Start by adding PlotlyJS to your environment:

(myWebsite) pkg> add PlotlyJS

Then, beyond the @def hasplotly = true, add the following code:

```julia:ex1
using PlotlyJS
z =  [10     10.625  12.5  15.625  20
     5.625  6.25    8.125 11.25   15.625
     2.5    3.125   5.    8.125   12.5
     0.625  1.25    3.125 6.25    10.625
     0      0.625   2.5   5.625   10]

data   = contour(; z=z)
layout = Layout(; title="Basic Contour Plot")
plt    = plot(data, layout)

fdplotly(json(plt)) # hide
```
\textoutput{ex1}

Note: the fdplotly is a convenience function exported by Franklin; it just prints the required HTML such that a plotly object gets placed. It takes the JSON string of the plot (which you can get with json(plt)) and takes two optional keyword arguments:

  • id: to specify the name of the div the plotly object is associated to, it's randomly generated by default, and,

  • style which takes a string indicating the desired CSS for the div e.g. the default is "width:600px;height:350px".

The code block above gives:

using PlotlyJS
z =  [10     10.625  12.5  15.625  20
     5.625  6.25    8.125 11.25   15.625
     2.5    3.125   5.    8.125   12.5
     0.625  1.25    3.125 6.25    10.625
     0      0.625   2.5   5.625   10]

data   = contour(; z=z)
layout = Layout(; title="Basic Contour Plot")
plt    = plot(data, layout)

Now you might use \fig{...} to insert graph just like normal. This also works fine with Plots.jl and PlotlyBase.jl.

Note: \fig{...} will call the JavaScript function PlotlyJS_json defined above. You might customize the behavior by modifying the JavaScript. Also, make sure @def hasplotly = true is properly set.

```julia:ex2
using PlotlyJS
p=plot(
     scatter(x=1:10, y=rand(10), mode="markers"),
     Layout(title="Responsive Plots")
     )
savejson(p, joinpath(@OUTPUT, "plotlyex.json"))  # savejson is an alternative to savefig # hide
# PlotlyBase.json (also exported by PlotlyJS) often gives a smaller json compared to PlotlyJS.savefig # hide
```

\fig{plotlyex}

This code block gives:

using PlotlyJS
p=plot(
     scatter(x=1:10, y=rand(10), mode="markers"),
     Layout(title="Responsive Plots")
     )

Note: The plot will be automatically resized when the browser window size changes due to the JavaScript function provided above. This, however, will ignore the layout.height and the layout.width supplied in the json. It gives good output in most cases. But if you need fine control over the size of the figure, please modify the JavaScript.