plotly redesign for splitting shapes
This commit is contained in:
parent
1cb0c0071b
commit
5407fa73f8
@ -336,8 +336,12 @@ plotly_data{R<:Rational}(v::AbstractArray{R}) = float(v)
|
|||||||
|
|
||||||
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
||||||
function plotly_series(plt::Plot, series::Series)
|
function plotly_series(plt::Plot, series::Series)
|
||||||
d = series.d
|
st = series[:seriestype]
|
||||||
sp = d[:subplot]
|
if st == :shape
|
||||||
|
return plotly_series_shapes(plt, series)
|
||||||
|
end
|
||||||
|
|
||||||
|
sp = series[:subplot]
|
||||||
d_out = KW()
|
d_out = KW()
|
||||||
|
|
||||||
# these are the axes that the series should be mapped to
|
# these are the axes that the series should be mapped to
|
||||||
@ -346,12 +350,11 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
d_out[:yaxis] = "y$spidx"
|
d_out[:yaxis] = "y$spidx"
|
||||||
d_out[:showlegend] = should_add_to_legend(series)
|
d_out[:showlegend] = should_add_to_legend(series)
|
||||||
|
|
||||||
x, y = plotly_data(d[:x]), plotly_data(d[:y])
|
x, y = plotly_data(series[:x]), plotly_data(series[:y])
|
||||||
d_out[:name] = d[:label]
|
d_out[:name] = series[:label]
|
||||||
st = d[:seriestype]
|
|
||||||
isscatter = st in (:scatter, :scatter3d, :scattergl)
|
isscatter = st in (:scatter, :scatter3d, :scattergl)
|
||||||
hasmarker = isscatter || d[:markershape] != :none
|
hasmarker = isscatter || series[:markershape] != :none
|
||||||
# hasline = !isscatter
|
|
||||||
hasline = st in (:path, :path3d)
|
hasline = st in (:path, :path3d)
|
||||||
|
|
||||||
# set the "type"
|
# set the "type"
|
||||||
@ -362,51 +365,36 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
else
|
else
|
||||||
hasline ? "lines" : "none"
|
hasline ? "lines" : "none"
|
||||||
end
|
end
|
||||||
if d[:fillrange] == true || d[:fillrange] == 0
|
if series[:fillrange] == true || series[:fillrange] == 0
|
||||||
d_out[:fill] = "tozeroy"
|
d_out[:fill] = "tozeroy"
|
||||||
d_out[:fillcolor] = rgba_string(d[:fillcolor])
|
d_out[:fillcolor] = rgba_string(series[:fillcolor])
|
||||||
elseif !(d[:fillrange] in (false, nothing))
|
elseif !(series[:fillrange] in (false, nothing))
|
||||||
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(d[:fillrange])")
|
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(series[:fillrange])")
|
||||||
end
|
end
|
||||||
d_out[:x], d_out[:y] = x, y
|
d_out[:x], d_out[:y] = x, y
|
||||||
|
|
||||||
elseif st == :shape
|
|
||||||
# to draw polygons, we actually draw lines with fill
|
|
||||||
d_out[:type] = "scatter"
|
|
||||||
d_out[:mode] = "lines"
|
|
||||||
d_out[:x], d_out[:y] = plotly_close_shapes(x, y)
|
|
||||||
d_out[:fill] = "tozeroy"
|
|
||||||
d_out[:fillcolor] = rgba_string(d[:fillcolor])
|
|
||||||
if d[:markerstrokewidth] > 0
|
|
||||||
d_out[:line] = KW(
|
|
||||||
:color => rgba_string(d[:linecolor]),
|
|
||||||
:width => d[:linewidth],
|
|
||||||
:dash => string(d[:linestyle]),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st == :bar
|
elseif st == :bar
|
||||||
d_out[:type] = "bar"
|
d_out[:type] = "bar"
|
||||||
d_out[:x], d_out[:y] = x, y
|
d_out[:x], d_out[:y] = x, y
|
||||||
d_out[:orientation] = isvertical(d) ? "v" : "h"
|
d_out[:orientation] = isvertical(series) ? "v" : "h"
|
||||||
|
|
||||||
elseif st == :heatmap
|
elseif st == :heatmap
|
||||||
d_out[:type] = "heatmap"
|
d_out[:type] = "heatmap"
|
||||||
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
|
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
|
||||||
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
|
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
|
||||||
|
|
||||||
elseif st == :contour
|
elseif st == :contour
|
||||||
d_out[:type] = "contour"
|
d_out[:type] = "contour"
|
||||||
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
|
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
|
||||||
# d_out[:showscale] = d[:colorbar] != :none
|
# d_out[:showscale] = series[:colorbar] != :none
|
||||||
d_out[:ncontours] = d[:levels]
|
d_out[:ncontours] = series[:levels]
|
||||||
d_out[:contours] = KW(:coloring => d[:fillrange] != nothing ? "fill" : "lines")
|
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
|
||||||
d_out[:colorscale] = plotly_colorscale(d[:linecolor], d[:linealpha])
|
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
|
||||||
|
|
||||||
elseif st in (:surface, :wireframe)
|
elseif st in (:surface, :wireframe)
|
||||||
d_out[:type] = "surface"
|
d_out[:type] = "surface"
|
||||||
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
|
d_out[:x], d_out[:y], d_out[:z] = series[:x], series[:y], transpose_z(series, series[:z].surf, false)
|
||||||
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
|
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
|
||||||
|
|
||||||
elseif st == :pie
|
elseif st == :pie
|
||||||
d_out[:type] = "pie"
|
d_out[:type] = "pie"
|
||||||
@ -422,7 +410,7 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
hasline ? "lines" : "none"
|
hasline ? "lines" : "none"
|
||||||
end
|
end
|
||||||
d_out[:x], d_out[:y] = x, y
|
d_out[:x], d_out[:y] = x, y
|
||||||
d_out[:z] = plotly_data(d[:z])
|
d_out[:z] = plotly_data(series[:z])
|
||||||
|
|
||||||
else
|
else
|
||||||
warn("Plotly: seriestype $st isn't supported.")
|
warn("Plotly: seriestype $st isn't supported.")
|
||||||
@ -432,32 +420,32 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
# add "marker"
|
# add "marker"
|
||||||
if hasmarker
|
if hasmarker
|
||||||
d_out[:marker] = KW(
|
d_out[:marker] = KW(
|
||||||
:symbol => get(_plotly_markers, d[:markershape], string(d[:markershape])),
|
:symbol => get(_plotly_markers, series[:markershape], string(series[:markershape])),
|
||||||
# :opacity => d[:markeralpha],
|
# :opacity => series[:markeralpha],
|
||||||
:size => 2 * d[:markersize],
|
:size => 2 * series[:markersize],
|
||||||
# :color => rgba_string(d[:markercolor]),
|
# :color => rgba_string(series[:markercolor]),
|
||||||
:line => KW(
|
:line => KW(
|
||||||
:color => rgba_string(d[:markerstrokecolor]),
|
:color => rgba_string(series[:markerstrokecolor]),
|
||||||
:width => d[:markerstrokewidth],
|
:width => series[:markerstrokewidth],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# gotta hack this (for now?) since plotly can't handle rgba values inside the gradient
|
# gotta hack this (for now?) since plotly can't handle rgba values inside the gradient
|
||||||
d_out[:marker][:color] = if d[:marker_z] == nothing
|
d_out[:marker][:color] = if series[:marker_z] == nothing
|
||||||
rgba_string(d[:markercolor])
|
rgba_string(series[:markercolor])
|
||||||
else
|
else
|
||||||
# grad = ColorGradient(d[:markercolor], alpha=d[:markeralpha])
|
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
|
||||||
grad = d[:markercolor]
|
grad = series[:markercolor]
|
||||||
zmin, zmax = extrema(d[:marker_z])
|
zmin, zmax = extrema(series[:marker_z])
|
||||||
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in d[:marker_z]]
|
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# add "line"
|
# add "line"
|
||||||
if hasline
|
if hasline
|
||||||
d_out[:line] = KW(
|
d_out[:line] = KW(
|
||||||
:color => rgba_string(d[:linecolor]),
|
:color => rgba_string(series[:linecolor]),
|
||||||
:width => d[:linewidth],
|
:width => series[:linewidth],
|
||||||
:shape => if st == :steppre
|
:shape => if st == :steppre
|
||||||
"vh"
|
"vh"
|
||||||
elseif st == :steppost
|
elseif st == :steppost
|
||||||
@ -465,32 +453,85 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
else
|
else
|
||||||
"linear"
|
"linear"
|
||||||
end,
|
end,
|
||||||
:dash => string(d[:linestyle]),
|
:dash => string(series[:linestyle]),
|
||||||
# :dash => "solid",
|
# :dash => "solid",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
plotly_polar!(d_out, series)
|
||||||
|
plotly_hover!(d_out, series[:hover])
|
||||||
|
|
||||||
|
[d_out]
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotly_series_shapes(plt::Plot, series::Series)
|
||||||
|
d_outs = []
|
||||||
|
|
||||||
|
# TODO: create a d_out for each polygon
|
||||||
|
# x, y = series[:x], series[:y]
|
||||||
|
|
||||||
|
# these are the axes that the series should be mapped to
|
||||||
|
spidx = plotly_subplot_index(series[:subplot])
|
||||||
|
base_d = KW()
|
||||||
|
base_d[:xaxis] = "x$spidx"
|
||||||
|
base_d[:yaxis] = "y$spidx"
|
||||||
|
base_d[:name] = series[:label]
|
||||||
|
# base_d[:legendgroup] = series[:label]
|
||||||
|
|
||||||
|
x, y = plotly_data(series[:x]), plotly_data(series[:y])
|
||||||
|
for (i,rng) in enumerate(iter_segments(x,y))
|
||||||
|
length(rng) < 2 && continue
|
||||||
|
|
||||||
|
# to draw polygons, we actually draw lines with fill
|
||||||
|
d_out = merge(base_d, KW(
|
||||||
|
:type => "scatter",
|
||||||
|
:mode => "lines",
|
||||||
|
:x => vcat(x[rng], x[rng[1]]),
|
||||||
|
:y => vcat(y[rng], y[rng[1]]),
|
||||||
|
:fill => "tozeroy",
|
||||||
|
:fillcolor => rgba_string(cycle(series[:fillcolor], i)),
|
||||||
|
))
|
||||||
|
if series[:markerstrokewidth] > 0
|
||||||
|
d_out[:line] = KW(
|
||||||
|
:color => rgba_string(cycle(series[:linecolor], i)),
|
||||||
|
:width => series[:linewidth],
|
||||||
|
:dash => string(series[:linestyle]),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
|
||||||
|
plotly_polar!(d_out, series)
|
||||||
|
plotly_hover!(d_out, cycle(series[:hover], i))
|
||||||
|
push!(d_outs, d_out)
|
||||||
|
end
|
||||||
|
d_outs
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotly_polar!(d_out::KW, series::Series)
|
||||||
# convert polar plots x/y to theta/radius
|
# convert polar plots x/y to theta/radius
|
||||||
if ispolar(d[:subplot])
|
if ispolar(series[:subplot])
|
||||||
d_out[:t] = rad2deg(pop!(d_out, :x))
|
d_out[:t] = rad2deg(pop!(d_out, :x))
|
||||||
d_out[:r] = pop!(d_out, :y)
|
d_out[:r] = pop!(d_out, :y)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotly_hover!(d_out::KW, hover)
|
||||||
# hover text
|
# hover text
|
||||||
hover = d[:hover]
|
|
||||||
if hover in (:none, false)
|
if hover in (:none, false)
|
||||||
d_out[:hoverinfo] = "none"
|
d_out[:hoverinfo] = "none"
|
||||||
elseif hover != nothing
|
elseif hover != nothing
|
||||||
d_out[:hoverinfo] = "text"
|
d_out[:hoverinfo] = "text"
|
||||||
d_out[:text] = hover
|
d_out[:text] = hover
|
||||||
end
|
end
|
||||||
|
|
||||||
d_out
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# get a list of dictionaries, each representing the series params
|
# get a list of dictionaries, each representing the series params
|
||||||
function plotly_series_json(plt::Plot)
|
function plotly_series_json(plt::Plot)
|
||||||
JSON.json(map(series -> plotly_series(plt, series), plt.series_list))
|
slist = []
|
||||||
|
for series in plt.series_list
|
||||||
|
append!(slist, plotly_series(plt, series))
|
||||||
|
end
|
||||||
|
JSON.json(slist)
|
||||||
|
# JSON.json(map(series -> plotly_series(plt, series), plt.series_list))
|
||||||
end
|
end
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|||||||
@ -33,10 +33,12 @@ end
|
|||||||
|
|
||||||
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
|
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
|
||||||
syncplot = plt.o
|
syncplot = plt.o
|
||||||
pdict = plotly_series(plt, series)
|
pdicts = plotly_series(plt, series)
|
||||||
typ = pop!(pdict, :type)
|
for pdict in pdicts
|
||||||
gt = PlotlyJS.GenericTrace(typ; pdict...)
|
typ = pop!(pdict, :type)
|
||||||
PlotlyJS.addtraces!(syncplot, gt)
|
gt = PlotlyJS.GenericTrace(typ; pdict...)
|
||||||
|
PlotlyJS.addtraces!(syncplot, gt)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
|
function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user