Hi everyone,
I recently wanted to use PlotlyJS directly in Pluto and still be able to view the plots in the static html export.
I just managed to somehow do that and wanted to post the procedure here to get feedback and eventually have a reference on discourse if anybody wants to achieve the same.
My need for PlotlyJS functionality in Pluto was due to the specific plot type I wanted to produce (Suburst Charts from the plotlyjs main library).
This trace, in fact, doesn’t seem to be exposed by the plotly/plotlyjs backend in Plots.jl and after asking on slack, I was told it would not be possible to plot this specific unsupported trace with Plots.jl without rewriting some code of the package itself.
While the use of WebIO is not yet officially supported, I managed to have a working PlotlyJS plot in pluto using the branch from this pull request.
All was working except that plots would not display on a static exported html file, which is normal as @fonsp pointed out in my comment in the pull request.
Trying to find a way to also make the static export work, I found a similar problem referenced in this issue.
I then tried adapting the proposed solution from @akdor1154 to have PlotlyBase plots show directly in the output of a pluto cell.
This is the piece of code that for me makes the Plot object correctly appear in the pluto cell both in the live notebook and in the static export.
using PlotlyBase, HypertextLiteral
# Custom abstract-trace array to string function
TraceData(data::Array{<:AbstractTrace}) = join(["[",join(string.(data),","),"]"])
function Base.show(io::IO, mimetype::MIME"text/html", p::PlotlyBase.Plot)
show(io,mimetype,@htl("""
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
<div style="height: auto">
<script>
let parentnode = currentScript.parentElement
Plotly.plot(parentnode,$(HypertextLiteral.JavaScript(TraceData(p.data))),$(HypertextLiteral.JavaScript(string(p.layout))),{responsive: true});
</script>
</div>
"""))
end
I suppose this breaks any possible interaction between julia and the plot which is coming from PlotlyJS, but I didn’t need that specifically.
Moreover, this also leaves PlotlyBase as the only dependency for plotting (and no requirement for the WebIO supporting branch of Pluto).
As I basically patched this solution without much knowledge about Javascript/HTML, I wanted to know whether there is something inherently wrong in adding the code above to a pluto cell in order to achieve what I wanted.
A potential issue I see is that I reference script containing the minfied plotlyjs code for each cell that contains a plot, but I have no idea how I could achieve the same functionality without putting the script inside the show function.
Here is also the source of the example .jl notebook for testing
Test notebook code
### A Pluto.jl notebook ###
# v0.14.5
using Markdown
using InteractiveUtils
# ╔═╡ a08c16a0-bc90-11eb-0274-e91d841ba34e
begin
import Pkg
Pkg.activate(".")
end
# ╔═╡ fa09788b-d9a6-496c-a126-4a1639211aaa
begin
using PlotlyBase
using HypertextLiteral
end
# ╔═╡ 923df2dc-3c00-493e-aac9-fbf03bd58fe7
begin
# Custom abstract-trace array to string function
TraceData(data::Array{<:AbstractTrace}) = join(["[",join(string.(data),","),"]"])
function Base.show(io::IO, mimetype::MIME"text/html", p::PlotlyBase.Plot)
show(io,mimetype,@htl("""
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
<div style="height: auto">
<script>
let parentnode = currentScript.parentElement
Plotly.plot(parentnode,$(HypertextLiteral.JavaScript(TraceData(p.data))),$(HypertextLiteral.JavaScript(string(p.layout))),{responsive: true});
</script>
</div>
"""))
end
end
# ╔═╡ 35c4a24e-c7e9-4b37-bc95-defb25f83f87
p = Plot(GenericTrace("sunburst",Dict(
:type => "sunburst",
:labels => ["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
:parents => ["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve" ],
:values => [50, 14, 12, 10, 2, 6, 6, 4, 0],
:leaf => Dict(:opacity => 0.4),
:marker => Dict(:line => Dict(:width => 1)),
:branchvalues => "total",
)))
# ╔═╡ Cell order:
# ╠═a08c16a0-bc90-11eb-0274-e91d841ba34e
# ╠═fa09788b-d9a6-496c-a126-4a1639211aaa
# ╠═923df2dc-3c00-493e-aac9-fbf03bd58fe7
# ╠═35c4a24e-c7e9-4b37-bc95-defb25f83f87
Edit: Added the TraceData function to correctly deal with multiple traces in a plot